3

HTML:

Filter: 
<input type="radio" ng-model="Type" value="Rear"> Rear
<input type="radio" ng-model="Type" value="Front"> Front
<br>
Select:
<name-value-select entry="entry" field="axleType" options="filterTypes"></name-value-select>

指令:

  .directive('nameValueSelect', function () {
    return {
    restrict: "E",
    scope: {
        entry: "=",
        field: "@",
        options: "=",
        onInputChange: "&"
    },
    controller: function ($scope) {

        $scope.onChange = function () {
            console.log("selected changed");
            $scope.entry.type = $scope.option.value;
            $scope.onInputChange();
        };

        var getItemForValue = function (value) {
            var item = null;
            $scope.options.forEach(function (_option) {
                if (_option.value == value) {
                    item = _option;
                }
            });
            return item;
        };

        $scope.$watch("entry", function () {
            console.log("entry changed");
            $scope.option = getItemForValue($scope.entry[$scope.field]);
        }, true);

    },
    template: '<select ng-model="option" ng-options="o.Description for o in options" ng-change="onChange()"><option value="" selected="selected">Please Select </option></select>'

};  })

コントローラ:

$scope.Description = '';
$scope.entry = {Description: ''};
$scope.Type = 'Front';
$scope.entry.type = '';


$scope.$watch('Type', function (Type) {
    $scope.filterTypes = [];
    $scope.axleTypes = new API.GetAxleTypes(function () {
        angular.forEach($scope.axleTypes, function(axleType) {
            if (axleType.Type == Type) {
                this.push(axleType);
            }
            // if(!$scope.$$phase) $scope.$digest(); // tried this, does not have any affect
    }, $scope.filterTypes); // '}, $scope.filterTypes, true)'--> did nothing for me here     
}); 
    $scope.filterTypes.sort(function (a, b) {
        return a.Description.localeCompare(b.Description);
    });
}); // '}, true)' --> did nothing for me here

問題:

カスタム選択コントロールは、最初にタイプ「フロント」のアイテムを取り込みます。リアをデフォルトにすると、「リア」も取り込まれます。

ただし、ラジオ ボタンを切り替えると、watch 関数は呼び出されず、select は新しく選択されたフィルター タイプを満たすアイテムを取り込みません。

/////////////////////////////////////////////// //// 問題を絞り込みました: /////////////////////////////////////// ////////////

これをスタンドアロン プロジェクトに移動すると、上記のコードが機能することがわかりました :-(

カスタム ディレクティブとしての元の select NOT は次のとおりです。

    <select ng-model="$parent.selectedFrontAxle" ng-options="axleType.Description for axleType in axleTypes | filterByType: 'Front' | orderBy:'Description'"  id="frontAxles" class="formRequire" required>            
        <option value="" selected>Select Axle Type ..</option>  
    </select>

カスタム ディレクティブとしての選択コントロールは次のとおりです。

  <name-value-select   entry="entry" field="axleType" options="filterTypes"></name-value-select>

明らかにこれが問題です: "ng-model="$parent.selectedFrontAxle"

include ステートメントの代わりに、ディレクティブ「name-value-select」を親ページに移動すると、機能します。

しかし、それは私が望むものではありません。したがって、インクルードページに残す必要があります。

しかし、ng-model="$parent.selectedFrontAxle"を取得してインクルード ページの任意の要素に追加しても、何も機能しません。

ng-model="$parent.selectedFrontAxle"がない場合でも、何も機能しません。

問題がスコープであることはわかりますが、修正方法はわかりません。

うーん!!! まだ解決策はありません。

//
//
/////////////////////////////////////////////////////////////////////// //////////////// マーク・ライコック ////////////////////////////// /////////////////////////////

いつもお世話になっております。ただし、ユーザーではなくコードを事前にフィルター処理するシナリオがあると言ったときに、ポイント 2 について明確にしたとは思いません。私はそれを理解しました。したがって、ディレクティブを介してコントロールを抽象化しようとしている人、およびこの場合のように、フィルタリング プロセスがユーザーとコードの両方で実行される場合は、プランカー ソリューションを次に示します。

http://plnkr.co/edit/tnXgPKADfr5Okvj8oV2S?p=preview

4

2 に答える 2

4

このplunkerでは、ユーザーが "Rear" または "Front" を選択できるようにコードを作り直し、選択リストが動的に更新されるようにしました。選択$scope.selected.itemした値は、MainCtrl スコープで使用できます。(削除したディレクティブには多くの不要なコードがありました。ng-model が使用されている場合、onChange ハンドラーは必要ありません。)

<name-value-select selected-item="selected.item" options="filterTypes">
</name-value-select>

app.directive('nameValueSelect', function () {
    return {
        restrict: "E",
        scope: {
            selectedItem: "=",
            options: '='
        },
        template: ...

ng-include は子スコープを作成するため、すべてのプリミティブ プロパティがオブジェクト プロパティに変換され、JavaScript プロトタイプの継承が期待どおりに機能します (つまり、値が変更されると、新しいプリミティブ プロパティが変更されるのではなく、MainCtrl で定義された $scope オブジェクトが変更されます)。ローカル スコープで作成されます)。

上記のプランカーがあなたの「ポイント1」を満たすと思います。

「ポイント2」のプランカーの作成を検討します...(この回答を更新するときにコメントを追加します)。


この plunkerは、ディレクティブの選択リストをフィルタリングします。

<name-value-select selected-item="selected.item" choice="choice.type"
 options="myTypes"></name-value-select>

app.directive('nameValueSelect', function () {
    return {
        restrict: "E",
        scope: {
            selectedItem: "=",
            choice:  "=",
            options: "=",
        },
        controller: function($scope)  {
          $scope.$watch('choice', function (selectedType) {
            $scope.selectedItem = '';  // clear selection
            $scope.filterTypes = [];
            angular.forEach($scope.options, function (type) {
              if (type.Type === selectedType) {
                this.push(type);
               }
            }, $scope.filterTypes);
            $scope.filterTypes.sort(function (a, b) {
              return a.Description.localeCompare(b.Description);
            });
          });
        },
        template: '<select ng-model="selectedItem" ' +
         'ng-options="o.Description for o in filterTypes">' +
         '<option value="" selected="selected">Please Select</option>' +
         '</select>'
    };
});
于 2013-04-24T22:10:55.770 に答える
-1

私はあなたの要求を正確に理解していませんが、ラジオボタングループの値に応じて選択の内容を動的に変更したいと思っていると思います. 選択はフィルタリングおよびソートされ、表示するデータのフィールドを選択できます。

少し変更を加えたデモを含むこのPlunkerを見たことがあるかもしれません。

HTML

Filter: 
<input type="radio" ng-model="filter.type" value="rear"> Rear
<input type="radio" ng-model="filter.type" value="front"> Front
<br />
Field:
<select ng-model="filter.field" ng-options="item for item in fields"></select>
<br />
Select:
<select ng-model="entry" ng-options="item[filter.field] for item in entries | filter:type=filter.type | orderBy:filter.field">
  <option value="">Default</option>
</select>
<br />
Selected: <span>{{entry}}</span>

<h2>Alternative</h2>
Filter: <span>{{filter}}</span>
<br />
<select ng-model="altentry" ng-options="item[filter.field] for item in altentries | orderBy:filter.field">
  <option value="">Default</option>
</select>
<br />
Selected: <span>{{altentry}}</span>

JS

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope) {
  $scope.name = 'World';

  /* Default filter values */
  $scope.filter = {
    type: 'rear',
    field: 'name'
  };

  /* List of fields */
  $scope.fields = [
    "id", "type", "name"
  ];

  /* Data coming from an API */
  $scope.entries = [
    {"id":1, "type":"rear", "name":"Rear Part 01"},
    {"id":2, "type":"rear", "name":"Rear Part 03"},
    {"id":3, "type":"rear", "name":"Rear Part 05"},
    {"id":4, "type":"rear", "name":"Rear Part 02"},
    {"id":5, "type":"rear", "name":"Rear Part 04"},
    {"id":6, "type":"front", "name":"Front Part 01"},
    {"id":7, "type":"front", "name":"Front Part 03"},
    {"id":8, "type":"front", "name":"Front Part 05"},
    {"id":9, "type":"front", "name":"Front Part 02"},
    {"id":10, "type":"front", "name":"Front Part 04"},
  ];

  /* Simulate different ajax return */
  $scope.$watch('filter.type', function(newval, oldval) {
    if (newval || newval !== oldval) {
      $scope.altentries = [];
      angular.forEach($scope.entries, function(v,k) {
        if (v.type === $scope.filter.type) {
          $scope.altentries.push(v);
        }
      });
    }
  });

  /* Monitoring any selected value */
  $scope.$watch('entry', function(newval, oldval) {
    console.log('entry:', oldval, newval);
  }, true);

  $scope.$watch('altentry', function(newval, oldval) {
    console.log('altentry:', oldval, newval);
  }, true);

});
于 2013-04-23T05:41:06.507 に答える