wake-up-neo.com

AngularJs: Wie funktioniert ui-select richtig?

DIE SITUATION:

Ich mache eine eckige App, bei der ich ui-select verwenden muss: Auf der Benutzerinfoseite muss in select möglich sein, ein oder mehrere Tags auszuwählen. Es funktioniert fast, außer dass ich Probleme habe, die vorhandenen Tags abzurufen und anzuzeigen.

DER CODE:

Aussicht:

<ui-select multiple ng-model="info_data.tags" theme="bootstrap" ng-disabled="disabled">

  <ui-select-match placeholder="Select tag...">{{$item.name}} </ui-select-match>

  <ui-select-choices repeat="tag in all_tags | propsFilter: {name: $select.search}">

    {{tag.name}}

  </ui-select-choices>

</ui-select>

<p>Selected: {{info_data.tags}}</p>

Controller:

$http({

    url: base_url + 'main/db_get_all_tags',
    method: "POST",

 }).success(function (data) {

    $scope.all_tags = data;

});

$scope.show_info = function() {

    var result_info = DbService.get_info( $stateParams.db_data_id );

    result_info.then( function( data )
    {
        $scope.info_data = data;

    });

};

VERSUCH 1:

Es passiert ein sehr merkwürdiges Verhalten. Ich sehe die Tags nicht auf der Infoseite des Benutzers und auch nicht in der UI-Auswahl. Außer wenn es 5/6 mal aktualisiert wird, funktioniert es plötzlich auf magische Weise und zeigt die Tags auf der Benutzerinfo-Seite und in der UI-Auswahl an. In beiden Fällen, funktionierend und nicht, erhalte ich mehrere Fehlermeldungen der gleichen Art:

Die Eigenschaft 'Länge' von undefined kann nicht gelesen werden.

VERSUCH 2:

Um dieses Problem zu beheben, habe ich den folgenden Code in den Controller eingefügt:

$scope.info_data = { tags: [] };
$scope. all_tags = [];

Und ich bekomme keine Fehlermeldung mehr. Die App ist stabil und ich kann die richtigen Tags auf der Benutzerinformationsseite sehen. Das einzige Problem ist, dass die Tags nicht mehr im UI-Select geladen werden.

Wenn ich ein neues Tag auswähle, funktioniert es einwandfrei, aber ich verliere die bereits vorhandenen Tags.

Fragen):

Wie kann ich UI-Select zum Laufen bringen? (aktuell v0.8.3) Gibt es ein Konfliktproblem?

Wie kann ich vorhandene Daten vom Server richtig abrufen?

Vielen Dank!

8
FrancescoMussi

Sie waren mit den Fehlern, die Sie sehen, nicht besonders beschreibend, daher weiß ich nicht, ob das Folgende hilft. 

Ich hatte ursprünglich ein Problem, als ich den Demo-Code für ui-select als Beispiel verwendete, weil sie den propsFilter - Filter verwenden, einen benutzerdefinierten Filter, den sie für die Demo geschrieben haben:

<ui-select-choices repeat="tag in all_tags | propsFilter: {name: $select.search}">

Ich gehe davon aus, dass Sie diesen Filter nicht in Ihren Code aufnehmen, was möglicherweise ein Grund dafür ist, dass Sie ein Problem haben. Sie können es auflösen, indem Sie den normalen filter des Winkels verwenden:

<ui-select-choices repeat="tag in all_tags | filter: {name: $select.search}">

Wenn Sie mehrere Eigenschaften zum Filtern haben, können Sie alternativ den propsFilter-Filter so schreiben, dass er auf OR anstatt auf UND filtert. Wenn Sie "filter" verwenden, um mehrere Eigenschaften zu filtern, wird versucht, den Suchwert in allen Eigenschaften zu finden.

app.filter('propsFilter', function() {
  return function(items, props) {
            var out = [];
                if (angular.isArray(items)) {
                  items.forEach(function(item) {
                        var itemMatches = false;

                        var keys = Object.keys(props);
                        for (var i = 0; i < keys.length; i++) {
                              var prop = keys[i];
                              var text = props[prop].toLowerCase();
                              if (item[prop].toString().toLowerCase().indexOf(text) !== -1) {
                                    itemMatches = true;
                                    break;
                                  }
                            }

                            if (itemMatches) {
                              out.Push(item);
                            }
                      });
                } else {
                  // Let the output be the input untouched
                      out = items;
                }

                return out;
          };
    });

sie können das Commit mit dem Filter hier sehen: https://github.com/angular-ui/ui-select/commit/3fac88cfad0ad2369c567142eadba52bdb7998b1

Wenn Sie jedoch bestimmte Filteranforderungen haben, würde ich Ihnen empfehlen, einen eigenen Filter zu schreiben, um eine optimale Leistung zu gewährleisten.

35
Nick Martin

Ich weiß nicht, wie die Situation vor Select2 # 4.0 war, aber es ist wirklich nicht so schwer, sie ohne angular-ui-select zu verwenden (und es ist eine weniger Abhängigkeit).

Fügen Sie einfach select2 in Ihre Bower-Abhängigkeiten ein und verwenden Sie es in Ihrer link-Funktion in der Direktive:

.directive('someDirective', function() {
    return {
        restrict: 'E',
        link: function(scope, element, attrs) {
            element.find('.your-select2').select2({
                theme: 'classic',
                placeholder: 'Select a placeholder...',
                allowClear: true,
                data: [{ id: 'New', text: 'New'}]...
            });
        },
    };
})

und dein HTML:

<select class="your-select2" ng-model="a.model.field"></select>

Sie können die Variable data auch über einen Dienst von der Steuerung laden, wenn Sie möchten. Verwenden Sie einfach die Variable scope, um sie einzustellen.

Ich sage das, als ich angular-ui-select ausprobiert habe, weil ich dachte "Hey, es ist Angular, du musst ein Plugin dafür!", Aber das ist nicht immer der Fall :). Außerdem fand ich die Dokumente nicht so hilfreich (nennen Sie mich faul aber hey)

3
a7omiton

Ich habe den propsFilter ein wenig optimiert. Es tut

props[prop].toLowerCase();

innerhalb der Elemente Iteration, aber dies muss tatsächlich nur so oft wie viele Eigenschaften ausgewertet werden, die wir haben. Derzeit wurde es ausgewertet items count * props count.

Der endgültige optimierte Code sieht also so aus:

app.filter('casinoPropsFilter', function() {
    return function(items, props) {
        var out = [];

        if (angular.isArray(items)) {
            var keys = Object.keys(props);
            var propCache = {};

            for (var i = 0; i < keys.length; i++) {
                var prop = keys[i];
                var text = props[prop].toLowerCase();
                propCache[props[prop]] = text;
            }

            items.forEach(function(item) {
                var itemMatches = false;

                for (var i = 0; i < keys.length; i++) {
                    var prop = keys[i];
                    var text = propCache[props[prop]];
                    if (item[prop].toString().toLowerCase().indexOf(text) !== -1) {
                        itemMatches = true;
                        break;
                    }
                }

                if (itemMatches) {
                    out.Push(item);
                }
            });
        } else {
            // Let the output be the input untouched
            out = items;
        }

        return out;
    };
});    

0