I have a directive rendering inputs based on a configuration sent by the server. Everything is working great except for the 'select' input. No matter what I try, the ng-model does not update. I have trimmed my code a lot to isolate the problem :
Javascript :
var myApp = angular.module('example', []);
myApp.factory('DynamicData', [function() {
return {
data: {
backup_frequency: 604800
}
};
}])
.directive('dynamicInput',
['$pile', 'DynamicData', function($pile, DynamicData) {
/**
* Render the input
*/
var render = function render() {
var input = angular.element('<select class="form-control" ng-model="inner.backup_frequency" ng-options="option.value as option.title for option in options"></select>');
return input;
};
var getInput = function ()
{
var input = render();
return input ? input[0].outerHTML : '';
};
var getTemplate = function(){
var template = '<div class="form-group">' +
'Select input ' +
'<div class="col-md-7">' + getInput() + '</div>' +
'</div>';
return template;
};
return {
restrict : 'E',
scope: {
content:'=content',
},
link : function(scope, element, attrs) {
var template = getTemplate();
scope.options = [
{title: "Daily", value: 86400},
{title: "Weekly", value: 604800},
{title: "Monthly", value: 2678400},
];
scope.inner = DynamicData.data;
console.info('inner data', scope.inner);
element.html(template);
element.replaceWith($pile(element.contents())(scope));
}
};
}])
.controller('FormCtrl', ['DynamicData', '$scope', function (DynamicData, $scope){
$scope.app = {};
$scope.save = function save() {
$scope.value = DynamicData.data.backup_frequency;
console.info('DynamicData', DynamicData.data);
};
}]);
HTML :
<head>
<script data-require="[email protected]" data-semver="1.3.8" src=".3.8/angular.js"></script>
<link href="style.css" rel="stylesheet" />
<script src="script.js"></script>
</head>
<body>
<h1>Dynamic Input :</h1>
<div data-ng-controller="FormCtrl">
<dynamic-input class="form-group" content="app"></dynamic-input>
<span data-ng-bind="value"></span><br/>
<button class="btn btn-primary" ng-click="save()">Save</button>
</div>
</body>
</html>
A working plunker is available :
Do you have any ideas why the ng-model in the select is not updated ?
EDIT : What I want to achieve is updating the variable "inner.backup_frequency" (the reference to my data object returned by my factory DynamicData). As you can see in the plunker, whenever I change the option in the select, the variable contained in the ng-model is not updated.
Thank you for your time.
I have a directive rendering inputs based on a configuration sent by the server. Everything is working great except for the 'select' input. No matter what I try, the ng-model does not update. I have trimmed my code a lot to isolate the problem :
Javascript :
var myApp = angular.module('example', []);
myApp.factory('DynamicData', [function() {
return {
data: {
backup_frequency: 604800
}
};
}])
.directive('dynamicInput',
['$pile', 'DynamicData', function($pile, DynamicData) {
/**
* Render the input
*/
var render = function render() {
var input = angular.element('<select class="form-control" ng-model="inner.backup_frequency" ng-options="option.value as option.title for option in options"></select>');
return input;
};
var getInput = function ()
{
var input = render();
return input ? input[0].outerHTML : '';
};
var getTemplate = function(){
var template = '<div class="form-group">' +
'Select input ' +
'<div class="col-md-7">' + getInput() + '</div>' +
'</div>';
return template;
};
return {
restrict : 'E',
scope: {
content:'=content',
},
link : function(scope, element, attrs) {
var template = getTemplate();
scope.options = [
{title: "Daily", value: 86400},
{title: "Weekly", value: 604800},
{title: "Monthly", value: 2678400},
];
scope.inner = DynamicData.data;
console.info('inner data', scope.inner);
element.html(template);
element.replaceWith($pile(element.contents())(scope));
}
};
}])
.controller('FormCtrl', ['DynamicData', '$scope', function (DynamicData, $scope){
$scope.app = {};
$scope.save = function save() {
$scope.value = DynamicData.data.backup_frequency;
console.info('DynamicData', DynamicData.data);
};
}]);
HTML :
<head>
<script data-require="[email protected]" data-semver="1.3.8" src="https://code.angularjs/1.3.8/angular.js"></script>
<link href="style.css" rel="stylesheet" />
<script src="script.js"></script>
</head>
<body>
<h1>Dynamic Input :</h1>
<div data-ng-controller="FormCtrl">
<dynamic-input class="form-group" content="app"></dynamic-input>
<span data-ng-bind="value"></span><br/>
<button class="btn btn-primary" ng-click="save()">Save</button>
</div>
</body>
</html>
A working plunker is available : http://plnkr.co/edit/mNBTJzZXjX6mLyPz6NCI?p=preview
Do you have any ideas why the ng-model in the select is not updated ?
EDIT : What I want to achieve is updating the variable "inner.backup_frequency" (the reference to my data object returned by my factory DynamicData). As you can see in the plunker, whenever I change the option in the select, the variable contained in the ng-model is not updated.
Thank you for your time.
Share Improve this question edited Feb 13, 2015 at 21:50 Alexandre Nucera asked Feb 13, 2015 at 12:03 Alexandre NuceraAlexandre Nucera 2,2232 gold badges22 silver badges34 bronze badges 3-
do you want that
<span data-ng-bind="value"></span><br/>
to be different each time I click.. or the value in select options to be valid.. please explain – Naeem Shaikh Commented Feb 13, 2015 at 12:18 - Hi, have you tried to fetch the on change event on the select and in javascript set the $scope.varaible and than $scope.$apply() just to see if it has something to do with the element being outside the $digest loop? – Andreas Commented Feb 15, 2015 at 13:53
- 1 See stackoverflow./a/22890796/446030 regarding order of pilation and placing within the dom. – JcT Commented Feb 15, 2015 at 14:00
2 Answers
Reset to default 13I had a similar issue and find if you directly bind ng-model to a scope variable as below, the scope variable selection somehow will not be updated.
<select ng-model="selection" ng-options="option for option in options">
Instead, define a view model in your scope and bind ng-model to a field of view model the view model field will be updated.
<select ng-model="viewmodel.selection" ng-options="option for option in options">
In your controller, you should do this:
app.controller('SomeCtrl', ['$scope'
function($scope)
{
$scope.viewmodel = {};
});
I've fixed it. What you needed to do was not to replace the element's content with the piled content, but rather replace it with the raw HTML and only then pile it.
element.html(template);
$pile(element.contents())(scope);
Working Plunker.
EDIT: I've edited your code to work without the directive:
Plunker without directive.
EDIT 2: Also a version where it works with the directive, but without the pile:
Plunker.