Ошибка связывания с Dropdown
У меня возникает проблема при привязке моего значения выпадающего списка с ассоциативным массивом.
Проблема связана с треком, так что, когда я не добавляю трек к моему выпадающему списку, тогда у меня есть привязка к раскрывающемуся списку, и когда я добавляю трек, тогда O не удается автоматически выбрать значение выпадающего списка.
Я хочу использовать track by с ng-options, чтобы angular js не добавлял
$$ hashKey и эффективность производительности, связанная с отслеживанием.
Я не понимаю, почему это происходит.
Примечание. Я хочу привязать название вариантов как Пицца или гамбургер для каждого из моих $scope.items, а не для всего объекта.
Обновление: Как я понимаю и с такой большой попыткой с текущей структурой данных моих $scope.items он не работает с ng-options, и я хочу использовать ng-options с треком на избегать генерации хеш-ключа angular js. Я также попробовал ng-change, как предложил @MarcinMalinowski, но я получаю ключ как undefined.
Итак, какова должна быть моя структура данных $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>
Ответы
Ответ 1
Проблемы в вашем коде:
1) track by $index
не поддерживается ngOptions
, это приведет к тому, что значение option
будет undefined
(в вашем случае это будет $index
of ngRepeat
);
2) track by
не работает с объектными данными-источниками (предполагается, что они используются с источниками данных массива), из документов:
trackexpr: используется при работе с массивом объектов. Результат это выражение будет использоваться для идентификации объектов в массиве.
Конечно, вы можете использовать ngRepeat
для генерации элементов option
, но лично я бы предпочел использовать ngOptions
без track by
из-за преимуществ, которые он имеет над 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
ngOptions
не создает новую область действия, например, директиву ngRepeat
для каждого элемента, поэтому вам не нужно заботиться о том, чтобы избавиться от $$hashKey
Я бы использовал ng-repeat
для итерации на <option>
(предположим, что вы не создаете длинные списки):
<select ng-model="data.myChoice">
<option value="">Select Connection</option>
<option ng-repeat="(key , value) in data.choices track by key" ng-value="key" title="{{key}}"
>{{key}}</option>
</select>
Рабочая демонстрационная скрипта
Посмотрите на эту проблему: github.com/angular/angular.js/issues/6564 - ng-options отслеживают и выбирают как несовместимые
Я считаю, что этот вопрос все еще существует, поэтому предложите использовать ngRepeat
с track by
. Для небольшого списка нет штрафа за производительность
Ответ 3
Вам нужно добавить ng-change
и передать/использовать ваше значение ng-model, чтобы получить любое свойство, которое вы хотите.
Ответ 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 или track by 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>
Или добавить ключевое имя внутри объекта выбора
$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>
Демо-ссылка Пример
Ответ 5
<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)">