Reputation: 21713
My plan was to create a specialized version of the ngOptions
directive that goes and fetches a select
's options from an external JSON source. My plan was to some inject the ngOptions
directive (the base) into my directive (the specialization).
angular.module('App.directives')
.directive ("selectDatasource", function ($http, ngOptions) {
return {
restrict: 'A',
link: function (scope, element, attrs) {
scope.dataSource = {};
attrs.ngOptions = "k as v for (k,v) in dataSource";
ngOptions.link (scope.element, attrs);
$http.get(attrs).success(function(r) { scope.dataSource = r; });
}
};
});
You could then use this as follows:
<select name="myOption" select-datasource="http://mysite/datasource"/>
However, ngOptions
fails to inject and I can't see how directives can be injected. I'm not sure this is the best approach anyway. If not, what is a good approach in general terms for specializing one of the built-in directives?
Upvotes: 2
Views: 123
Reputation: 54649
You could do the following:
app.directive('selectDatasource', ['Loader', function (Loader) {
return {
scope: true,
compile: function (tElement, attr) {
attr.ngOptions = 'v.value as v.label for v in values';
return function link(scope) {
Loader.load(attr.selectDatasource).then(function (response) {
scope.values = response;
});
};
}
};
}]);
though because of the predefined format of ngOptions
you'd lose a lot of flexibility. Thus it might be better to use something like:
app.directive('datasource', ['Loader', function (Loader) {
return function (scope, element, attr) {
// add to scope
scope[attr.datasourceTarget] = [];
// observer changes
attr.$observe('datasource', function (nv, ov) {
if (nv !== ov) {
Loader.load(nv).then(function (response) {
scope[attr.datasourceTarget] = response;
});
}
});
};
}]);
with:
<select
data-ng-model="test2"
data-datasource="http://mysite/datasource"
data-datasource-target="values"
data-ng-options="v.value as v.label for v in values"
></select>
demo:
Upvotes: 1
Reputation: 4801
Do not remove ng-options from select. Instead write new directive that fetches data from external source and sets scope variable, which then is used by the ng-options. Something like this:
//template
<select ng-model="myModel.myValue" ng-options="k as v for (k,v) in dataSource" select-data-source="http://mysite/datasource/"></select>
//directive
module.directive('selectDataSource', function($http) {
return {
link: function($scope, $element, $attrs) {
var url = $attrs.selectDataSource;
$http.get(url).success(function(response) {
$scope.dataSource = response;
});
}
}
})
Upvotes: 1