Ankündigung

Einklappen
Keine Ankündigung bisher.

Dynamische Optionen für basic.select

Einklappen
X
 
  • Filter
  • Zeit
  • Anzeigen
Alles löschen
neue Beiträge

    Dynamische Optionen für basic.select

    Hallo Gemeinde,

    ich bin gerade ein klein wenig am verzweifeln. smartVISU ist bisher noch absolutes Neuland für mich, habe bis vor ein paar Tagen noch TabletUI in verbindung mit FHEM genutzt.

    Soweit läuft bisher auch alles zufriedenstellend, aber und nun geht es daran, eigene Widgets zu erstellen. Klappt bisher auch ganz gut für das, was ich brauche, nur bei einer Sache komme ich nicht weiter

    Ich möchte ein <select> mit Daten befüllen mit $(this).append(newOption).selectmenu('refresh'). Nur schmeißt mir smartVISU in der Konsole immer ein "Uncaught TypeError: b is undefined" raus. Funktioniert .append() bei dem neuen $.sv.widget Format nicht mehr, oder was übersehe ich hier?

    Hier der Auszug aus meiner my.js
    Code:
    $.widget("sv.my_enigma_channel", $.sv.widget, {
      
      initSelector: '[data-widget="my.enigma_channel"]',
      
        _init: function() {
        },
          
        _update: function(response) {
          var channelList = "";
          $.each(response[1].split(","), function(index, value) {
            channelList += "<option value=\"" + value + "\">" + value.replace(/_/g, ' ') + "</option>";
          });
          $(this).append(channelList).selectmenu('refresh');
        },
    
        _events: {
          'change': function(event) {
            this._write(this.element.val());
          }
        }
    });
    Und hier der Auszug aus my.html
    Code:
    {% macro enigma_channel(id, channel, channelList) %}
      <select name="{{ uid(page, id) }}" id="{{ uid(page, id) }}"  data-widget="my.enigma_channel" data-item="{{ channel }}, {{ channelList }}" data-native-menu="false" data-placeholder="false" />
      </select>
    {% endmacro %}
    Zuletzt geändert von wvhn; 23.07.2020, 23:27. Grund: Titel zwecks besserer Dokumentation geändert

    #2
    Hallo und herzlich willkommen im Forum,

    im initSelector fehlt das html-Element vor dem data-widget:
    Code:
    initSelector: 'select[data-widget="my.enigma_channel"]'
    Die append() Funktion braucht dies IMHO, um die channelList
    an das richtige Element anzuhängen.

    Gruß
    Wolfram

    Kommentar


      #3
      Danke für die Antwort. Schande über mein Haupt, welch ein dummer fehler meinerseits... Sitze da seit ein paar Tagen über mich selbst fluchend dran. Werde es nach feierabend sofort zu Haus ändern!

      Kommentar


        #4
        Leider bekomme ich auch mit dem select vor dem data-widget den Fehler "Uncaught TypeError: b is undefined"

        Kommentar


          #5
          Mit dem alten Code würde es hingegen funktionieren, habe als Test folgendes probiert, und die Option wird ohne Probleme hinzugefügt.
          Code:
          $(document).delegate('select[data-widget="my.enigma_channel"]', {
            'update': function (response) {
              $(this).val(response).selectmenu('refresh');
              $("#"+this.id+" option[value='"+response+"']").attr('selected',true);
              $(this).append('<option value="test">test</option>').selectmenu('refresh');
            },
          
            'change': function (event) {
              var items = $(this).attr('data-item').explode();
              io.write(items[0], $(this).val() );
            }
          });

          Kommentar


            #6
            Hattest Du den Cache gelöscht, bevor Du die Änderung getestet hast?
            Und hast Du Dir die Variable ChannelList mal ausgeben lassen und geprüft, ob der String für die Options richtig aufgebaut ist? Mich irritiert ehrlich gesagt die Funktion $.each, die in DOM gleichartige Elemente sucht, die ich aber nicht als Ersatz für eine FOR-Schleife kenne.

            Kommentar


              #7
              Ja, channelList ist richtig aufgebaut, habe ich zum Test ins log schreiben lassen und der Cache ist auch leer. Auch wenn ich versuche nur eine einzelne Option hinzuzufügen wie im alten Code bekomme ich den Fehler. Ich könnte es natürlich mit dem alten Code bauen da es dort funktioniert, aber das will ich eigentlich nicht.

              The $.each() function is not the same as $(selector).each(), which is used to iterate, exclusively, over a jQuery object. The $.each() function can be used to iterate over any collection, whether it is an object or an array. In the case of an array, the callback is passed an array index and a corresponding array value each time.

              Kommentar


                #8
                Wenn Du Dir den Sourcecode in der Entwicklerkonsole anschaust, müsste doch zu sehen sein, ob die Optionen in den html-Code eingebettet werden.
                In der uppdate-Methode besteht IMHO zusätzlich das Problem, dass der aktualisierte Wert des zu setzenden items nicht gesetzt wird. Hier wäre das this.element.val ...

                Ich muss mal sehen, dass ich das morgen zum Test irgendwo einbaue. Eine flexible select-Liste steht nämlich als issue schon länger auf der Feature-Wunschliste für das widget basic.select.

                Kommentar


                  #9
                  Also ich möchte damit meine Dreambox steuern, bzw. den Kanal umschalten können. channel ist der laufende Kanal als auch der zu schaltende Kanal. channelList ist die Liste der möglichen Kanäle getrennt durch komma. Mit diesem Code hier funktioniert es wie es soll. Ich bekomme die Kanäle in das <select> und kann auch umschalten. Nur wie gesagt ist diese Methode ja in 2.9 deprecated und ich würde gerne das neue Format nutzen wollen, nur dort hapert es an dem .append().

                  Code:
                  $(document).delegate('select[data-widget="my.enigma_channel"]', {
                    'update': function (event, response) {
                      var channelList = "";
                      $.each(response[1].split(","), function(index, value) {
                        channelList += "<option value=\"" + value + "\">" + value.replace(/_/g, ' ') + "</option>";
                      });
                      $(this).empty().append(channelList);
                      $("#"+this.id+" option[value='"+response[0]+"']").attr('selected',true);
                      $(this).selectmenu('refresh');
                  },
                  
                    'change': function (event) {
                        var items = $(this).attr('data-item').explode();
                        io.write(items[0], $(this).val());
                        $(this).trigger(update);
                    }
                  });
                  Zuletzt geändert von ReviloEgros; 19.07.2020, 03:12.

                  Kommentar


                    #10
                    Kurze Zwischenmeldung: Es liegt nicht an dem .append(), sondern am $(this). Mit
                    Code:
                    this.element.append(channelList).selectmenu('refresh');
                    funktioniert das Select Element. Allerdings wird die gesamte ChannelList bei jedem item-Update erneut angehängt, so dass die Liste immer länger wird. Das muss noch abgefangen werden. Hierzu gibt es zwei Möglichkeiten:
                    1. die Liste in der _create-Methode aufbauen. Dann wird sie aber nur einmalig beim Seitenaufbau erzeugt und bleibt statisch
                    2. die Optionen bei jedem Update aus der Seite entfernen und neu aufbauen. Dann ist die Liste dynamisch
                    Die _update Methode wird übrigens jedes Mal aufgerufen, wenn sich das item ODER die Liste ändern.

                    Die Methode _init gibt es nicht. Die kannst Du weglassen.

                    Kommentar


                      #11
                      So. Dieser Code funktioniert bei meinen Tests gut:
                      Code:
                      $.widget("sv.my_enigma_channel", $.sv.widget, {
                         
                        initSelector: 'select[data-widget="my.enigma_channel"]',
                         
                          _update: function(response) {
                            // response is item to set and listitem (array) with available values
                      	  var channelList = "";
                      	  this.element.find('option').remove();
                      	  var respvar= response[1].toString();
                      	  	  
                            $.each(respvar.split(","), function(index, value) {
                              channelList += "<option value=\"" + value + "\">" + value.replace(/_/g, ' ') + "</option>";
                            });
                      	  this.element.append(channelList);
                      	  this.element.find("option[value='"+response[0]+"']").attr('selected',true);
                      	  this.element.selectmenu('refresh');
                          },
                      
                          _events: {
                            'change': function(event) {
                              this._write(this.element.val());
                            }
                          }
                      });
                      Ich habe allerdings die ChannelList als List Item angelegt in der Form [1, 2, 3, 4, 5] und übergebe das aus shNG. Wenn ich das item im Admin-Interface ändere, wird die Liste in der Visu aktualisiert.
                      Nächster Schritt ist noch der Ersatz der $.each-Schleife durch eine FOR-Schleife, weil ich dann mit demselben Index noch eine zweite Liste durchlaufen kann, die den item-Werten individuelle Texte zuweist (optional). Damit hätten wir dann die "menu"-Option von basic.select dynamisch gemacht.
                      Für Deine my.js sollte das aber erstmal reichen. Wenn Du einfach nur einen String als ChannelList hast, kannst Du die toString()-Funktion weglassen.

                      Kommentar


                        #12
                        Das sieht schon ziemlich cool aus - könnte man auch super für das KODI Plugin nutzen (Wahl der UT und Sprachspur), was meinst du, Morg ?

                        Kommentar


                          #13
                          Ich hab das jetzt in basic.select (type="menu") eingebaut und hier zur Verfügung gestellt, damit ihr es in Eure bestehende Version einbauen könnt. (Für Abenteurer ebenfalls im develop verfügbar)

                          Es gibt jetzt ein item "itemvals" für die wählbaren Optionen (an das Backend zu sendende Werte), sowie ein item "itemtxts" für die zugehörigen Texte. Wenn letzteres fehlt, werden die Werte aus dem ersten item als Text verwendet. Beide items müssen als list items vom Backend gesendet werden. Es findet (anders als im obigen Beispiel) keine Formatierung bzw. Ersatz von Zeichen statt.

                          Sonstige im widget-Aufruf angegebene Werte- und Textlisten werden ignoriert, sobald das item "itemvals" definiert ist.

                          Für Tester bin ich immer dankbar!

                          Kommentar


                            #14
                            Vielen lieben dank, das hat mir sehr geholfen!

                            Kommentar


                              #15
                              @wvhn

                              Moin,
                              ich habe deinen code in der basic.html und basic.js ergänzt.

                              Jedoch bekomme ich es nicht zum laufen.

                              Ich möchte gerne in der Visu folgende Werte anzeigen -Automatik, Manuell, Urlaub, Abwesend, Sommerbetrieb.
                              Genau diese Werte möchte ich dann auch weitergeben.

                              Ich habe es so in den html code eingefügt, es kommen aber nur 0 und 1 zur Auswahl.

                              Code:
                              {{ basic.select('', 'Heizung_Wozi.multistate', '', '', '', '', [Automatik,Manuell,Urlaub,Abwesend,Sommerbetrieb], ['Automatik', 'Manuell', 'Urlaub', 'Abwesend', 'Sommerbetrieb']) }}
                              Was mache ich falsch?
                              Mit freundlichen Grüßen

                              Edit:
                              Hat sich erledigt.

                              So funktioniert es jetzt
                              Code:
                              {{ basic.select('', 'Heizung_Wozi.multistate', '', ['Automatik', 'Manuell', 'Urlaub', 'Abwesend', 'Sommerbetrieb'], '', ['Automatik', 'Manuell', 'Urlaub', 'Abwesend', 'Sommerbetrieb']) }}
                              Zuletzt geändert von Shadow3561; Gestern, 15:31.

                              Kommentar

                              Lädt...
                              X