Angular ng-model 动态 getter 和 setter
Angular ng-model dynamic getters and setters
我想将 ng-model 与外部模型服务一起使用。该模型有两个方法:getValue(variable) 和 setValue(variable)。
所以在我的 html 中,我希望能够做到:
<input type="text" ng-model="balance">
Note: balance is not defined on $scope in my controller. And because we are dealing with more then 4000 different variables, I don't want to define them all on $scope.
然后在更改时它必须调用模型的 setValue() 方法。所以在我的控制器中我想有这样的东西:
$catchAllGetter = function(variable) { // e.g. variable = 'balance'
var value = Model.getValue(variable);
return value;
}
$catchAllSetter = function(variable, value) { // called on change
Model.setValue(variable, value);
}
Angular 可以实现这样的功能吗?
您可以创建一个实现此行为的新指令。
<input model-getter='getFn()' model-setter='setFn($value)' />
这将很容易实现:
app.directive('modelGetter', function() {
return {
restrict: 'A',
scope: {
get: '&modelGetter',
set: '&modelSetter'
},
link: function(scope, element) {
element.val(scope.get());
element.on('change', function() {
var val = element.val();
scope.set({ $value: val });
});
}
};
})
看看example,我为你创造的。希望我理解正确
$scope.$watch('variables', function(newValue) {
console.log("triggers on variables change");
angular.forEach(newValue, function(value, key) {
Model.setValue(key, value);
});
}, true);
我的方法和@Dan Prince类似,但是实现有点不同
创建一个接受模型变量名称的指令,然后在指令本身中注入您的模型服务以执行获取和设置。
Edit : As specified by @Werlang, writing an attribute that replaces
ngModel will refrain you from features like validation, formatting,
debounced update, ng-change etc. So instead of writing a replacement,
we will instead wire up a supplementary attribute
。
app.directive('dynamicInput', function() {
return {
restrict: 'A',
link: function(scope, el, attr) {
scope.variableName = angular.copy(attr.ngModel); // Saving the variable name
scope[attr.ngModel] = (attr.ngModel + '_1'); // Setting a dummy value in the scope variable.
// In your case it will look something like scope[attr.ngModel] = Model.getValue(attr.ngModel);
scope.$watch(attr.ngModel, function(newValue, oldValue) {
console.log(scope.variableName + " ==> " + newValue);
//Model.setValue(scope.variableName, newValue);
});
}
};
})
然后在你的 HTML 中:
<input ng-model='balance' dynamic-input />
将所有变量放在一个对象数组中:
[
{key: "Variable 1", value: 1, kind: "number"},
{key: "Variable 2", value: "some text", kind: "text"},
{key: "Variable 3", value: new Date(), kind: "date"}
]
然后在您看来,您将在 ng-repeat 的帮助下创建它们:
<div ng-repeat="variable in myVariables">
<input type="{{variable.kind}}" ng-model="variable.value" ng-change="changed(variable)">
</div>
如果您需要更新您的外部服务,请在您的控制器中实现一个方法 changed(variable)。
ngModel
支持 getter 和设置器。它是这样工作的:
<input ng-model="balance" ng-model-options="{ getterSetter: true }">
如果 balance
是一个 getter/setter 函数,这有效:
$scope.balance(100); // sets 100
var b = $scope.balance(); // returns 100
您不需要公开作用域上的每个变量 - 您可以只公开您在示例中使用的 Model
服务:
$scope.Model = Model;
然后,在视图中,绑定到您需要的任何 属性:
<input ng-model="Model.balance" ng-model-options="{ getterSetter: true }">
ES5 对象属性来拯救:
Object.defineProperty($scope, 'balance', {
enumberable: true,
get: function () {
// -- call your getter here
},
set: function (val) {
// -- call the setter here
}
});
这是本机 Javascript,因此没有比这更快的了。
您可以动态评估您的模型功能,例如
<input type="text" ng-model="myModel(var)">
在控制器中:
$scope.myModel = function(var) {
return function(newValue) {
// this is a regular model function but you can use 'var' here
...
}
}
我想将 ng-model 与外部模型服务一起使用。该模型有两个方法:getValue(variable) 和 setValue(variable)。
所以在我的 html 中,我希望能够做到:
<input type="text" ng-model="balance">
Note: balance is not defined on $scope in my controller. And because we are dealing with more then 4000 different variables, I don't want to define them all on $scope.
然后在更改时它必须调用模型的 setValue() 方法。所以在我的控制器中我想有这样的东西:
$catchAllGetter = function(variable) { // e.g. variable = 'balance'
var value = Model.getValue(variable);
return value;
}
$catchAllSetter = function(variable, value) { // called on change
Model.setValue(variable, value);
}
Angular 可以实现这样的功能吗?
您可以创建一个实现此行为的新指令。
<input model-getter='getFn()' model-setter='setFn($value)' />
这将很容易实现:
app.directive('modelGetter', function() {
return {
restrict: 'A',
scope: {
get: '&modelGetter',
set: '&modelSetter'
},
link: function(scope, element) {
element.val(scope.get());
element.on('change', function() {
var val = element.val();
scope.set({ $value: val });
});
}
};
})
看看example,我为你创造的。希望我理解正确
$scope.$watch('variables', function(newValue) {
console.log("triggers on variables change");
angular.forEach(newValue, function(value, key) {
Model.setValue(key, value);
});
}, true);
我的方法和@Dan Prince类似,但是实现有点不同
创建一个接受模型变量名称的指令,然后在指令本身中注入您的模型服务以执行获取和设置。
Edit : As specified by @Werlang, writing an attribute that replaces ngModel will refrain you from features like validation, formatting, debounced update, ng-change etc. So instead of writing a replacement, we will instead wire up a supplementary attribute
。
app.directive('dynamicInput', function() {
return {
restrict: 'A',
link: function(scope, el, attr) {
scope.variableName = angular.copy(attr.ngModel); // Saving the variable name
scope[attr.ngModel] = (attr.ngModel + '_1'); // Setting a dummy value in the scope variable.
// In your case it will look something like scope[attr.ngModel] = Model.getValue(attr.ngModel);
scope.$watch(attr.ngModel, function(newValue, oldValue) {
console.log(scope.variableName + " ==> " + newValue);
//Model.setValue(scope.variableName, newValue);
});
}
};
})
然后在你的 HTML 中:
<input ng-model='balance' dynamic-input />
将所有变量放在一个对象数组中:
[
{key: "Variable 1", value: 1, kind: "number"},
{key: "Variable 2", value: "some text", kind: "text"},
{key: "Variable 3", value: new Date(), kind: "date"}
]
然后在您看来,您将在 ng-repeat 的帮助下创建它们:
<div ng-repeat="variable in myVariables">
<input type="{{variable.kind}}" ng-model="variable.value" ng-change="changed(variable)">
</div>
如果您需要更新您的外部服务,请在您的控制器中实现一个方法 changed(variable)。
ngModel
支持 getter 和设置器。它是这样工作的:
<input ng-model="balance" ng-model-options="{ getterSetter: true }">
如果 balance
是一个 getter/setter 函数,这有效:
$scope.balance(100); // sets 100
var b = $scope.balance(); // returns 100
您不需要公开作用域上的每个变量 - 您可以只公开您在示例中使用的 Model
服务:
$scope.Model = Model;
然后,在视图中,绑定到您需要的任何 属性:
<input ng-model="Model.balance" ng-model-options="{ getterSetter: true }">
ES5 对象属性来拯救:
Object.defineProperty($scope, 'balance', {
enumberable: true,
get: function () {
// -- call your getter here
},
set: function (val) {
// -- call the setter here
}
});
这是本机 Javascript,因此没有比这更快的了。
您可以动态评估您的模型功能,例如
<input type="text" ng-model="myModel(var)">
在控制器中:
$scope.myModel = function(var) {
return function(newValue) {
// this is a regular model function but you can use 'var' here
...
}
}