Seeking help with a directive that produces a select list. I'm trying to pass in the id and value keys of the object for reusability. However, the list isn't binding to its parent model when it's updated. Any ideas on why this might be happening?
index.html
<!doctype html>
<html ng-app="app">
<head>
</head>
<body>
<div ng-controller="Ctrl">
<my-dir list="characters"
model="model.character"
selected-item="model.character.id"
value-key="id"
text-key="name">
</my-dir>
<button ng-click="check()">Check</button>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.8/angular.js"></script>
<script src="script.js"></script>
</body>
</html>
script.js
var app = angular.module('app', []);
app.controller('Ctrl', function($scope) {
$scope.model = { character: { id: 2, name: 'Link' } };
$scope.characters = [
{ id: 1, name: 'Mario' },
{ id: 2, name: 'Link' },
{ id: 3, name: 'Bowser' }
];
$scope.check = function() {
alert($scope.model.character.name);
};
});
app.directive('myDir', function() {
return {
restrict: 'E',
controller: function($scope) {
},
template: "<select ng-model='vm.model'>"
+ "<option value=''></option>"
+ "<option ng-repeat='item in vm.list' ng-selected='item[vm.valueKey]===vm.selectedItem' "
+ "value='item[vm.valueKey]' ng-bind='item[vm.textKey]'>"
+ "</option>"
+ "</select>",
controllerAs: 'vm',
bindToController: true,
scope: {
model:'=',
list:'=',
valueKey:'@',
textKey:'@',
selectedItem:'='
}
};
});
Edit:
This solution works, but is there a cleaner way to handle the blank option without creating clutter? Open to suggestions.
<select ng-model="vm.model" ng-options="item as item[vm.textKey] for item in vm.list track by item[vm.valueKey]"></select>
Edit 2:
Is there a method to make the blank option actually bind to the model with null properties instead of setting the entire model as null when selected?
For instance, selecting the blank value should result in:
$scope.model = { character: { id: null, name: null } };
Rather than:
$scope.model = { character: null };
This refactor would be beneficial for a reusable control like this one. It would be preferable to implement it here rather than altering source data for every object array to include a null value.
I managed to tackle this issue using:
<select ng-model="vm.model" ng-change="selectChange()" ng-options="item as item[vm.textKey] for item in vm.list track by item[vm.valueKey]">
<option value=""></option>
</select>
...
$scope.selectChange = function () {
if ($scope.vm.model === null) {
var blankItem = {};
blankItem[$scope.vm.valueKey] = null;
blankItem[$scope.vm.textKey] = null;
$scope.vm.model = blankItem;
}
};