【发布时间】:2014-03-22 19:30:16
【问题描述】:
我正在尝试创建一个指令,允许我绑定到其他范围属性的散列。
HTML
<div lookup lookup-model="data.countryId"></div>
<div lookup lookup-model="data.stateId" lookup-params="{countryId: data.countryId}"></div>
我希望能够做的是每次更新查找参数中的值以使用 data.stateId 的模型刷新查找。我试图保持这个通用性,因为我可能想要拥有各种不同的查找参数。
有没有办法在 Angular 中做到这一点?
更新
我当然没有提供足够的细节。点击提交太快了。这是我基于@Olivvv 反馈的解决方案。该建议将我引向scope.$eval 函数。
这里的目标是创建一个指令,允许我们使用带有$http get 的选择来为选择中的选项播种。一些$http 请求将需要一个参数,因为它们依赖于另一个值。例如,只有在提供国家/地区值时才能提供一组状态。
以下是我整理的代码。我确信它可以改进,但目前它正在发挥作用。请注意,我将 Lodash 用于一些实用功能。您还将看到一个范围对象“lookupModelObject”。这纯粹是为了满足样式选择的设计需求。如果您只对lookupParams 感兴趣,可能可以忽略它。
HTML 片段
<div select-lookup lookup-value="block.data.countryId" lookup-type="countries" lookup-placeholder="Select a Country"></div>
<div select-lookup lookup-value="block.data.stateId" lookup-type="states" lookup-params="{countryId: block.data.countryId}" lookup-placeholder="Select a State"></div>
指令
要指出的重要部分是我如何评估attrs.lookupParams。如果该属性存在,我使用scope.$eval 来评估该属性。稍后您将看到我如何将每个参数添加到范围,并添加一个观察者以防其中一个参数发生更改。如果选择了不同的国家,这将允许我将“状态”重置为 null。
angular.module("foo").directive('selectLookup', ['$http', '$q', function($http, $q) {
return {
restrict: 'A',
replace: true,
templateUrl: 'common/lookups/partials/selectLookupPartial.html',
scope: {
id: "@",
lookupValue: "=",
lookupParams: "="
},
link: function(scope, element, attrs) {
// Initialize the options.
scope.options = [];
var optionsLoaded = false;
var resetLookupModel = function() {
scope.lookupModelObject = {
id: null,
text: attrs.lookupPlaceholder
};
};
// Evaluate and obtain the lookup parameters for this lookup.
var lookupParams = {};
if (attrs.lookupParams) {
lookupParams = scope.$eval(attrs.lookupParams);
}
var updateLookupModelObject = function(value) {
// This function is only relevant if the options have been loaded.
if (optionsLoaded) {
if (value === undefined || value === null) {
resetLookupModel();
}
else {
var item = _.findWhere(scope.options, {id: value});
if (item) {
scope.lookupModelObject = item;
}
else {
resetLookupModel();
}
}
}
};
var fetchValues = _.throttle(function() {
var deferred = $q.defer(),
fetchUrl = "/api/lookup/" + attrs.lookupType,
keys = _.keys(lookupParams);
_.each(keys, function(key, index) {
if (index === 0) {
fetchUrl += "?";
}
else {
fetchUrl += "&";
}
fetchUrl += key + "=" + lookupParams[key];
});
// Empty the options.
scope.options.splice(0, scope.options.length);
$http.get(fetchUrl).then(function(response) {
scope.options = response.data;
optionsLoaded = true;
updateLookupModelObject(scope.lookupValue);
deferred.resolve(scope.options);
});
return deferred.promise;
}, 150);
// Setup the watchers
// If there are lookup params add them to scope so we can watch them.
var keys = _.keys(lookupParams);
_.each(keys, function(key) {
scope[key] = lookupParams[key];
// Setup watchers for each param.
scope.$watch(key, function() {
fetchValues();
});
});
scope.$watch('lookupParams', function(newValue, oldValue) {
if (!_.isEqual(newValue, oldValue)) {
lookupParams = newValue;
fetchValues().then(resetLookupModel);
}
});
scope.$watch('lookupValue', updateLookupModelObject);
scope.$watch('lookupModelObject', function(newValue, oldValue) {
if (!_.isEqual(newValue, oldValue)) {
scope.lookupValue = newValue.id;
}
});
fetchValues();
}
};
}]);
模板
我们的设计约束迫使我们引入“选择占位符”。除此之外,选择是在 Angular 中设置选择的“典型”方式。
<div class="container select-container">
<div class="select-placeholder">
<span class="select-placeholder-text">{{ lookupModelObject.text }}</span>
<select class="select-input" data-ng-model="lookupModelObject" id="{{ id }}" data-ng-options="option as option.text for option in options"></select>
</div>
</div>
【问题讨论】:
-
更多关于图片其余部分的细节会有所帮助。
-
是的,只是不完全清楚目标是什么......我想你可能想要像lookupModel[lookupParams]这样的东西,其中lookupParams绑定到一个字符串,这样你就可以获得模型的特定属性,但可以根据目前的情况,不能肯定地说。您能否介绍一下您的指令定义或展示一个 plunkr 或 jsfiddle 示例?
标签: angularjs angularjs-directive