Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular ng-model dynamic getters and setters

I want to use ng-model with an external model-service. This model has two methods: getValue(variable) and setValue(variable).

So in my html I want to be able to do:

<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.

And then on change it must call the setValue() method of the model. So in my controller I would like to have something like:

$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);
}

Is something like this possible with Angular?

like image 402
Jan-Paul Kleemans Avatar asked Apr 15 '15 10:04

Jan-Paul Kleemans


3 Answers

My approach is similar to @Dan Prince, but the implementation differs a bit

Create a directive, that accepts name of the model variable, and then inject your model service in the directive itself to perform the getting and setting.

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);

              });

        }
      };
    })

Then in your HTML :

    <input ng-model='balance' dynamic-input />
like image 59
Manish Kr. Shukla Avatar answered Sep 24 '22 06:09

Manish Kr. Shukla


You can create a new directive which implements this behaviour.

<input model-getter='getFn()' model-setter='setFn($value)' />

This would be fairly straightforward to implement:

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 });
      });
    }
  };
})
like image 37
Dan Prince Avatar answered Sep 25 '22 06:09

Dan Prince


look at example, i created for you. I hope I have understood you correctly

$scope.$watch('variables', function(newValue) {
  console.log("triggers on variables change");
  angular.forEach(newValue, function(value, key) {
    Model.setValue(key, value);
  });  
}, true);
like image 36
saygon91 Avatar answered Sep 25 '22 06:09

saygon91