web-dev-qa-db-ja.com

AngularJs:ui-selectを適切に機能させるにはどうすればよいですか?

状況:

Ui-selectを使用する必要があるangularアプリを作成しています:ユーザー情報ページで、selectで1つまたは複数のタグを選択できる必要があります。既存のタグを取得して表示するのに問題があるという事実から。

コード:

表示:

<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>

コントローラー:

$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;

    });

};

試行1:

これは非常に奇妙な動作です。ユーザーの情報ページにも、ui-selectにもタグが表示されません。 5/6回更新する場合を除いて、突然それは魔法のように機能し、ユーザー情報ページとui-selectにタグを表示します。どちらの場合も、機能していても機能していなくても、同じ種類のエラーメッセージがいくつか表示されます。

未定義のプロパティ「長さ」を読み取ることができません。

アテンプト2:

この問題を解決するために、コントローラーに次のコードを追加しました。

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

そして、私はもうエラーメッセージを受け取りません。アプリは安定しており、ユーザー情報ページで適切なタグを確認できます。唯一の問題は、タグがui-selectにロードされなくなったことです。

新しいタグを選択すると正常に機能しますが、既存のタグが失われます。

QUESTION(s):

Ui-selectを正しく機能させるにはどうすればよいですか? (現在v0.8.3)競合の問題はありますか?

サーバーから既存のデータを適切に呼び出すにはどうすればよいですか?

どうもありがとうございました!

9
FrancescoMussi

あなたはあなたが見ているエラーについて特に説明していないので、以下が役立つかどうかはわかりません。

彼らが書いたカスタムフィルターであるpropsFilterフィルターを使用しているため、例としてui-selectデモコードを使用するときに最初に問題がありましたデモの場合:

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

このフィルターをコードに含めていないことを前提としています。これが問題が発生している理由である可能性があります。 Angularの法線filterを使用して解決できます:

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

または、フィルタリングするプロパティが複数ある場合は、propsFilterフィルタを記述して、ANDではなくOR)でフィルタリングできます。「filter」を使用して複数のプロパティをフィルタリングすると、検索値の照合が試行されます。すべてのプロパティにわたって。

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;
          };
    });

ここでフィルターを含むコミットを確認できます: https://github.com/angular-ui/ui-select/commit/3fac88cfad0ad2369c567142eadba52bdb7998b1

ただし、特定のフィルタリング要件がある場合は、最適なパフォーマンスを確保するために独自のフィルターを作成することをお勧めします。

39
Nick Martin

Select2#4.0以前の状況はわかりませんが、angular-ui-selectなしで使用するのはそれほど難しいことではありません(依存関係が1つ少なくなります)

バウアー依存関係にselect2を含め、ディレクティブ内のlink関数で使用するだけです。

.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'}]...
            });
        },
    };
})

およびHTML:

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

必要に応じて、サービスを介してコントローラーからdataをロードし、scopeを使用して設定することもできます。

私がangular-ui-selectを使ってみたとき、私はこれを言っています。さらに、ドキュメントはあまり役に立ちませんでした(怠惰と呼んでくださいがねえ)

3
a7omiton

PropsFilterを少し最適化しました。やっている

props[prop].toLowerCase();

アイテムの反復内ですが、これは実際には、プロパティの数倍だけ評価する必要があります。現在評価されていますitems count * props count

したがって、最終的に最適化されたコードは次のようになります。

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