I am trying to show an array of data with ng-repeat directive of AngularJS. This html code works under the same controller and have the same scope with constants
variable updated async:
<div class="popup3" id="constant_insert">
<h2>Insert constant</h2>
<select id="constants" ng-model="clonedModel.category" ng-options="c.name for c in constants"></select>
<div ng-repeat="c in constants">
<input type="radio" ng-model="model.selected" ng-value="c"/> {{ c.name }} <br/>
</div>
<div style="clear: both; height: 20px;"></div>
<div id="confirm" class="save_button">Insert</div>
<div id="cancel" class="save_button">Cancel</div>
</div>
ng-options works with my data and shows the content of the constants
but ng-repeat is not.
The resulting HTML is this:
<div class="popup3 ng-scope visible" id="constant_insert">
<h2>Insert constant</h2>
<select id="categories" ng-model="clonedModel.category" ng-options="c.name for c in constants" class="ng-pristine ng-valid"><option value="?" selected="selected"> </option><option value="0">aa</option><option value="1">ee</option></select>
<!-- ngRepeat: c in constants -->
<div style="clear: both; height: 20px;"></div>
<div id="confirm" class="save_button">Insert</div>
<div id="cancel" class="save_button">Cancel</div>
</div>
Yes, data is from async call, and this html generated from template by transclude directive but as far as ng-options shows the data, all this usuall scope.$apply stuff is already done and it seems to me its unrelevant to the problem, so I omit all these code. The question is - why ng-repeat cannot work with the data ng-options capable to work with? Whats so special about ng-repeat? Is there any gotchas I need to know about? Ofc if I make a simple controller with this html template then both of the directives will work. But I am trying to find a bug and it hides somewhere in the diffrences of how these directives handles the data.
Thanx!
PS:
the directive:
.directive('modalDialog', function ($compile, $http, Notification) {
return {
restrict: 'A',
transclude: true,
replace: false,
scope: {
confirm: '&',
cancel: '&',
init: '&',
model: '='
},
link: function postLink(scope, element, attrs) {
app.log('modal link');
//clone model
scope.clonedModel = {};
scope.isNew = attrs.creating ? true : false;
app._clone(scope.model, scope.clonedModel, false);
var modal = $('<div class="overlay"></div>');
modal.attr('id', scope.$id);
var dialog;
var _dialog;
if (attrs.templateId) {
dialog = $('#' + attrs.templateId).clone();
bind();
} else if (attrs.partialName) {
$http.get('partials/' + attrs.partialName + '.html', {cache: true}).then(function (response) {
modal.html(response.data);
dialog = modal.children();
bind();
});
}
function closeDialog(button) {
app.log('modal close');
button.off('click');
modal.removeClass('visible');
_dialog.removeClass('visible');
scope.$apply(function () {
scope.cancel()
});
}
function bindConfirm(button) {
app.log('bind confirm');
button.on('click', function () {
app.log('clear bind confirm');
button.off('click');
app._clone(scope.clonedModel, scope.model, false);
scope.confirm({model: scope.model, isNew: scope.isNew}).then(function () {
app.log('dialog scope confirm');
//succeeded
modal.removeClass('visible');
_dialog.removeClass('visible');
}, function (response) {
//failed
var errorMessage = response.data ? response.data : "Unknown error, status code:" + response.status;
Notification.notify('Error', errorMessage, 4000);
});
});
}
function bind() {
app.log('modal bind');
scope.init({model: scope.clonedModel, localScope: scope});
_dialog = $compile(dialog)(scope);
var button = _dialog.find('#confirm');
$('input, textarea', _dialog).first().trigger('focus');
$(_dialog).keyup(function (event) { //close on Esc
// app.log("Key pressed: ");
// app.log(event);
if (event.which == 27) closeDialog(button);
});
_dialog.find('#cancel').on('click', function () {
closeDialog(button);
});
element.on('click', function () {
app.log('modal element click');
bindConfirm(button);
//copy model into scope local var
scope.clonedModel = {};
scope.$apply(function(scope){
app._clone(scope.model, scope.clonedModel, false);
scope.init({model: scope.clonedModel, localScope: scope});
});
$(modal).appendTo('body');
$(_dialog).appendTo('body');
modal.addClass('visible');
_dialog.addClass('visible');
});
scope.$on('$destroy', function () {
modal.remove();
dialog.remove();
});
}
}
}
})
this is how it is called from html:
<div id="insert_constant" class="green_button small_button" template-id="constant_insert" style="float: left; position: relative;" model="const" confirm="onConstInsert(model, template)" init="initConstantDialog(model, localScope)" modal-dialog ng-transclude>Constants</div>
and this is init function from scope:
$scope.initConstantDialog = function (model, localScope) {
localScope.constants = $scope.constants;
app.log("init constants dialog");
app.log(model);
app.log(localScope);
}
constants contains this:
[{"id":8,"name":"aa","oldName":"aa","value":"aa"},{"id":9,"name":"ee","oldName":"ee","value":"ee"}]
AngularJS v1.2.10