Set model value programmatically in Angular.js

I am the author of the angular-input-modified directive.

This directive is used to track the value of a model and allows you to check whether a value has been changed, and also provides a reset() function to change the value to its original state.

Currently, the initial value of the model is stored in the ngModelController.masterValue property and the ngModelController.reset() function is ngModelController.reset() . See implementation .

I use the following statement: eval('$scope.' + modelPath + ' = modelCtrl.masterValue;'); to return the value back to its original state. modelPath Here is actually the value of the ng-model attribute. It was designed back, and I don't like this approach, because the ng-model value can be complex, and nested areas will violate this functionality.

What is the best way to reorganize this statement? How to update model value directly through ngModel controller interface?

+2
source share
2 answers

The best solution I've found so far is to use the $ parse service to parse the Angular expression in ng-model and get the setter function for it. Then we can change the model value by calling this setter function with a new value.

Example:

 function reset () { var modelValueSetter = $parse(attrs.ngModel).assign; modelValueSetter($scope, 'Some new value'); } 

This works much more reliably than eval() .


If you have an idea, please provide another answer or just comment on it. Thanks!

+2
source

[previous answer]

I had a problem with this problem today, and I solved it by starting and sorting the $parsers pipeline capture using closure.

 const hijack = {trigger: false; model: null}; modelCtrl.$parsers.push( val => { if (hijack.trigger){ hijack.trigger = false; return hijack.model; } else { // .. do something else ... }) 

Then, to reset the model, you need to start the pipeline by changing $viewValue to modelCtrl.$setViewValue('newViewValue') .

 const $setModelValue = function(model){ // trigger the hijack and pass along your new model hijack.trigger = true; hijack.model = model; // assuming you have some logic in getViewValue to output a viewValue string modelCtrl.$setViewValue( getViewValue(model) ); } 

Using $setViewValue() , you will call the $parsers . Then the function that I wrote in the first block of code will be executed using val = getViewValue(model) , after which it will try to analyze it for something that needs to be used for your $modelValue according to the logic there. But for now, the closing variable captures the parser and uses it to completely overwrite the current $ modelValue.

At this point, val not used in $parser , but it will still be the actual value displayed in the DOM, so choose a good one.

Let me know if this approach suits you.

[edit]

It seems like ngModel. $ commitViewValue should also start the $ parsers pipeline, I tried quickly, but could not get it to work.

0
source

Source: https://habr.com/ru/post/1209541/


All Articles