javascript - 意味 - doc angularjs
トラックのドロップダウンバインディングの問題 (4)
ngOptions属性を使用して、配列またはオブジェクトを使用して要素の要素のリストを動的に生成することができます
ngModelは、値ではなく参照によってモデルを監視します。 これは、選択をオブジェクトまたはコレクションであるモデルにバインドするときを知る上で重要です。
1.モデルをコレクション内のオブジェクトと等しいオブジェクトに設定すると、オブジェクトが同一ではないため、ngOptionsは選択を設定できません。 したがって、デフォルトでは、コレクション内のアイテムを事前選択のために参照する必要があります。例:$ scope.selected = $ scope.collection [3]
- ngOptionsは、参照によってではなく、式によるトラックの結果によってアイテムのアイデンティティを追跡します。 たとえば、コレクションアイテムにidプロパティがある場合、item.idで追跡します。
例えば :
$scope.items = [
{
"title": "1",
"myChoice" :"",
"choices": {
"pizza": {
"type": 1,
"arg": "abc"
},
"burger": {
"type": 1,
"arg": "pqr"
}
}
},
{
"title": "2",
"myChoice" :"",
"choices": {
"pizza": {
"type": 1,
"arg": "abc"
},
"burger": {
"type": 1,
"arg": "pqr"
}
}
}
];
上記の2番目のポイントから、参照ではなくアイテムの識別情報を追跡します。
オブジェクトにキーのkeyNameを追加し、keyNameでトラックを追跡するか、またはarg、typeでトラックを追跡します。
argか型で追跡する:
<select ng-model="data.myChoice"
ng-options="choice as choice.arg for choice in data.choices track by choice.arg">
<option value="">Select Connection</option>
</select>
または、choiceオブジェクトの中にkeyNameを追加する
$scope.items = $scope.items.filter(function(item){
delete item.myChoice;
item.choices = Object.keys(item.choices).map(function(choice){
item.choices[choice].keyName = choice;
return item.choices[choice];
});
return item;
});
HTMLコード:
<div ng-controller="MyCtrl">
<ul>
<div ng-repeat="data in items">
<select ng-model="data.selected"
ng-options="choice as choice.keyName for choice in data.choices track by choice.keyName"
ng-change="selection(data.selected)">
<option value="">Select</option>
</select>
</div>
</ul>
</div>
デモリンクのExample
私は連想配列で私のドロップダウン値をバインドする際に問題を抱えています。
私のドロップダウンにトラックを追加しないと、ドロップダウンでバインドされてしまい、トラックを追加するときにドロップダウン値を自動選択できなくなってしまったような問題がトラックの問題です。
ng-optionsでtrack byを使用して、angle jsが$$ hashKeyを追加せず、track byに関連するパフォーマンス上の利点を活用したいと思います。
なぜこのような現象が起こっているのか分かりません。
注:私は$ scope.itemsごとにピザやバーガーのような選択肢の名前をバインドしたいだけで、 オブジェクト全体にはバインドしません 。
Update:私が理解しているように、$ scope.itemsの現在のデータ構造を試してみると、ng-optionsで動作していないので、Angular jsによるハッシュキーの生成を避けるために、ng-optionsをトラックで使用したい。 @MarcinMalinowskiが提案したようにng-changeも試みましたが、私は未定義のキーを取得しています。
だから私の$ scope.itemsから任意の項目にアクセスする必要があるように、$ scope.itemsの私のデータ構造にする必要がありますか? 私は正しいデータ構造で現在どのようにアクセスできるか、トラックでのみngoptionsを使用するような、ループを行わずに(私たちは連想配列から項目にアクセスするように)アクセスできます。
var app = angular.module("myApp", []);
app.controller("MyController", function($scope) {
$scope.items = [
{
"title": "1",
"myChoice" :"",
"choices": {
"pizza": {
"type": 1,
"arg": "abc",
"$$hashKey": "object:417"
},
"burger": {
"type": 1,
"arg": "pqr",
"$$hashKey": "object:418"
}
}
},
{
"title": "2",
"myChoice" :"",
"choices": {
"pizza": {
"type": 1,
"arg": "abc",
"$$hashKey": "object:417"
},
"burger": {
"type": 1,
"arg": "pqr",
"$$hashKey": "object:418"
}
}
}
];
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<ul ng-app="myApp" ng-controller="MyController">
<div ng-repeat="data in items">
<div>{{data.title}}
</div>
<select ng-model="data.myChoice"
ng-options="key as key for (key , value) in data.choices track by $index"><option value="">Select Connection</option></select>
</div>
</ul>
ng-change
を追加し、そこにng-modelの値を渡して使用する必要があります。
コード内の問題は次のとおりです。
1) track by $index
はngOptions
でサポートされていないので 、 option
の値はundefined
になります( ngRepeat
$index
にngRepeat
)。
2) track by
は、オブジェクトデータソース(配列データソースと一緒に使用されるはずです)、 docs :
trackexpr:オブジェクトの配列を操作するときに使用されます。 この式の結果は、配列内のオブジェクトを識別するために使用されます。
もちろん、 ngRepeat
を使用してoption
要素を生成することもできますが、個人的には、 ngRepeat
利点により、 track by
なしでngOptions
を使用することをngOptions
ngRepeat
ます。
UPDATE:モデルがオブジェクトの場合にオプションを事前に選択するために、初期データソースを変更してtrack by
を使用する方法を示すコードを示します。 しかし、最初の例でも、 console.log()
は$$hashKey
がchoices
オブジェクトに追加されていないことを示しています。
var app = angular.module("myApp", []);
app.controller("MyController", ['$scope', '$timeout', function($scope, $timeout) {
$scope.items = [
{
"title": "1",
"myChoice" :"burger",
"choices": {
"pizza": {
"type": 1,
"arg": "abc"
},
"burger": {
"type": 1,
"arg": "pqr"
}
}
},
{
"title": "2",
"myChoice" :"",
"choices": {
"pizza": {
"type": 1,
"arg": "abc"
},
"burger": {
"type": 1,
"arg": "pqr"
}
}
}
];
$scope.itemsTransformed = angular.copy($scope.items).map(function(item){
delete item.myChoice;
item.choices = Object.keys(item.choices).map(function(choice){
item.choices[choice].name = choice;
return item.choices[choice];
});
return item;
});
//select an option like an object, not a string
$scope.itemsTransformed[1].myChoice = $scope.itemsTransformed[1].choices[0];
$timeout(function() {
//changes a prop in opts array - options are not-re-rendered in the DOM
//the same option is still selected
$scope.itemsTransformed[1].choices[0].arg = "xyz";
}, 3000);
$scope.selectionChanged =function(key, items){
console.log(items); //as we can see $$hashKey wasn't added to choices props
};
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<ul ng-app="myApp" ng-controller="MyController">
<p>Without track by:</p>
<div ng-repeat="data in items track by data.title">
<div>{{data.title}} - {{data.myChoice}}</div>
<select ng-model="data.myChoice"
ng-options="key as key for (key , value) in data.choices"
ng-change="selectionChanged(key, items)">
<option value="">Select Connection</option>
</select>
</div>
<hr/>
<p>Using track by name to pre-select an option:</p>
<div ng-repeat="data in itemsTransformed track by data.title">
<div>{{data.title}} - {{data.myChoice}}</div>
<select ng-model="data.myChoice"
ng-options="choice as choice.name for choice in data.choices track by choice.name"
ng-change="selectionChanged(key, itemsTransformed)">
<option value="">Select Connection</option>
</select>
</div>
</ul>
更新2: track by
なしのngOptions
を使用している場合、 $$hashKey
プロパティがオブジェクトに追加されないという事実を示す簡単な例:
var app = angular.module("myApp", []);
app.controller("MyController", ['$scope', '$timeout', function ($scope, $timeout) {
$scope.items = {
"pizza": {
"type": 1,
"arg": "abc"
},
"burger": {
"type": 1,
"arg": "pqr"
}
};
$scope.selectionChanged = function (key, items) {
console.log($scope.items);
};
}]);
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MyController">
<hr/>
<p>Example without track by:</p>
<select ng-model="myChoice"
ng-options="key as key for (key , value) in items"
ng-change="selectionChanged(myChoice, items)">
<option value="">Select Connection</option>
</select>
<hr/>
{{myChoice}}
</div>
UPDATE 3:以下の最終結果(anglejsバージョンが1.4未満の場合1.4 $scope.itemsTransformed
、最初のコードスニペットで$scope.itemsTransformed
としてデータ構造を変更することをお勧めします):
angular.module("myApp", [])
.controller("MyController", ['$scope', function ($scope) {
$scope.items = [
{
"title": "1",
"myChoice": "burger",
"choices": {
"pizza": {
"type": 1,
"arg": "abc"
},
"burger": {
"type": 1,
"arg": "pqr"
}
}
},
{
"title": "2",
"myChoice": "",
"choices": {
"pizza": {
"type": 1,
"arg": "abc"
},
"burger": {
"type": 1,
"arg": "pqr"
}
}
}
];
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="MyController">
<div ng-repeat="data in items track by data.title">
<div>{{data.title}} {{data.myChoice}}</div>
<select ng-model="data.myChoice"
ng-options="key as key for (key , value) in data.choices">
<option value="">Select Connection</option>
</select>
</div>
</div>
<select class="form-control pickupaddress ng-pristine ng-valid ng-touched m-r-sm m-t-n-xs" ng-model="item.pickup_address" tabindex="0" aria-invalid="false" ng-options="add._id as add.nick_name for add in addPerFood[item.food._id] | unique:'nick_name'" ng-change="dropDownSelect(item.pickup_address,allCarts,item,$index)">