Reputation: 65
I am using the directive multiple times on the page like
<div data-escape-amp-curation-multi-value-selector
data-binding-path="model"
data-search-key="journeys"
data-current-selection-model="model.journeys">
</div>
<div data-escape-amp-curation-multi-value-selector
data-binding-path="model"
data-search-key="targets"
data-current-selection-model="model.targets">
</div>
My directive looks like
var directive : ng.IDirective = {
restrict : 'A',
template : '<select multiple="multiple" data-options="sources/>',
compile() {
return {
pre(scope : any, element : any, attrs : any) {
scope.readonly = attrs.readonly === 'true';
},
post(scope : any, element : any, attrs : any) {
var binder = $parse(attrs.currentSelectionModel),
valueDropDown = element.find('select.value-dropdown'),
kendoMultiSelect = valueDropDown.data('kendoMultiSelect'),
defer = $q.defer();
/**
* The method to do search.
* @type {void}
*/
scope.doSearch = () = > {
scope.showSpinner = true;
scope.$evalAsync(() = > {
if (!cache) {
metadataService.getMetadata(attrs.searchKey).then(
result = > {
cache = result;
scope.sources = result;
defer.resolve();
},
error = > {
defer.reject(error);
});
} else {
scope.sources = cache;
defer.resolve();
}
defer.promise.then(() = > {
kendoMultiSelect.setDataSource(scope.sources);
scope.showSpinner = false;
kendoMultiSelect.value(binder(scope));
});
});
};
kendoMultiSelect.bind('change', () = > {
binder.bind(scope, kendoMultiSelect.value());
});
/**
* Set cache to null on location change
*/
scope.$on(LOCATION_CHANGE_START, () = > {
cache = null;
});
scope.$watch(() = > scope.$eval(attrs.currentSelectionModel), () = > {
if (!scope.sources) {
if (angular.isDefined(cache) && cache !== null) {
$timeout(() = > {
scope.sources = cache;
kendoMultiSelect.setDataSource(scope.sources);
kendoMultiSelect.value(binder(scope));
});
} else {
scope.doSearch();
}
} else {
kendoMultiSelect.setDataSource(scope.sources);
kendoMultiSelect.value(binder(scope));
}
});
}
}
}
}
When this code renders it gives call to backend service to populate sources based on the search key but scope.sources for bot instance gets the same value. It gets the value of last search service call. What I am missing here? Thanks.
Upvotes: 4
Views: 2618
Reputation: 44916
scope
is prototypically inherited in Angular, but a new scope is only created if you request it. In this case, you are simply decorating the existing scope defined by the parent that your directive is sitting in.
This means that anything added to scope will be overwritten by the same directive.
You can tell your directive to create a new scope by simply adding the scope:true
property to your directive definition object:
{
restrict : 'A',
scope:true
//more stuff
}
Here is a simple example to show the difference between a directive that creates a new scope, and one that does not.
(function() {
'use strict';
function NoNewScope() {
return {
restrict: 'A',
template: [
'<div class="form-group">',
' <label>Name - <code>{{name}}</code></label>',
' <input class="form-control" type="text" ng-model="name" />',
'</div>'
].join(''),
link: function(scope) {
scope.name = "No New Scope";
}
};
}
function NewScope() {
return {
restrict: 'A',
scope: true,
template: [
'<div class="form-group">',
' <label>Name - <code>{{name}}</code></label>',
' <input class="form-control" type="text" ng-model="name" />',
'</div>'
].join(''),
link: function(scope) {
scope.name = "New Scope";
}
};
}
angular.module('my-app', [])
.directive('noNewScope', NoNewScope)
.directive('newScope', NewScope);
}());
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<div ng-app="my-app" class="container">
<div class="row">
<div class="col-xs-6">
<h3>NO new scope</h3>
<div no-new-scope></div>
<div no-new-scope></div>
</div>
<div class="col-xs-6">
<h3>NEW scope</h3>
<div new-scope></div>
<div new-scope></div>
</div>
</div>
</div>
Upvotes: 3