Editing Multiple Variables Using a Single Model

Is there a way to edit three different variables using just one model? Because in the current approach it looks like only the variable value is copied to "editVar".

Code script below

<div ng-controller="MyCtrl">
    A: {{A}}<br/> B: {{B}} <br/> C: {{C}}<br/>
    <input ng-model="editedVar"/>
    <br/>
    <button ng-click="switchToA()">Switch to A</button>
    <button ng-click="switchToB()">Switch to B</button>
    <button ng-click="switchToC()">Switch to C</button>
</div>




var myApp = angular.module('myApp',[]);

function MyCtrl($scope) {
$scope.A = 1;
$scope.B = 2;
$scope.C = 3;

    $scope.switchToA = function()
    {
        $scope.editedVar = $scope.A;    
    };

    $scope.switchToB = function()
    {
        $scope.editedVar = $scope.B;    
    };

    $scope.switchToC = function()
    {
        $scope.editedVar = $scope.C;    
    };
}

      

+3


source to share


3 answers


You could do it in different ways, here is a simpler and drier way.

View (just keep them just as one function to change the currently edited var): -

<input ng-model="editedVar[editing]" />
<br />
<button ng-click="switchTo('A')">Switch to A</button>
<button ng-click="switchTo('B')">Switch to B</button>
<button ng-click="switchTo('C')">Switch to C</button>

      

Controller: -

function MyCtrl($scope) {
    /*Keep the values in an object with respective property name*/
    $scope.editedVar = {
        A: 1,
        B: 2,
        C: 3
    }

    /*Set the default edit property*/
    $scope.editing = 'A';

    /*Sets the currently edited property based on what is being passed in*/    
    $scope.switchTo = function (prop) {
        $scope.editing = prop;
    };

}

      

Fiddle



You can also do this, but only with a lot of maintenance code without using an object.

View: -

<input ng-model="editedVar" ng-change="valueChange()"/>
<br/>
<button ng-click="switchTo('A')">Switch to A</button>
<button ng-click="switchTo('B')">Switch to B</button>
<button ng-click="switchTo('C')">Switch to C</button>

      

Controller: -

function MyCtrl($scope) {

    $scope.A = 1;
    $scope.B = 2;
    $scope.C = 3;

    var editing;
    /*Change event to keep the value in sync*/
    $scope.valueChange = function(){
        $scope[editing] = $scope.editedVar;
    }
    /*Just one function*/
    $scope.switchTo = function (prop) {
        $scope.editedVar = $scope[editing = prop];
    };

}

      

Fiddle

+3


source


What you want is a two way link binding with a non primitive type, see below:



<div ng-controller="MyCtrl">
    A: {{A.val}}<br/> B: {{B.val}} <br/> C: {{C.val}}<br/>
    <input ng-model="editedVar.val"/>
    <br/>
    <button ng-click="switchToA()">Swithc to A</button>
    <button ng-click="switchToB()">Swithc to B</button>
    <button ng-click="switchToC()">Swithc to C</button>
</div>



var myApp = angular.module('myApp',[]);

function MyCtrl($scope) {
    $scope.A = {val: 1};
    $scope.B = {val: 2};
    $scope.C = {val: 3};

    $scope.switchToA = function()
    {
        $scope.editedVar = $scope.A;    
    };

    $scope.switchToB = function()
    {
        $scope.editedVar = $scope.B;    
    };

    $scope.switchToC = function()
    {
        $scope.editedVar = $scope.C;    
    };
}

      

+1


source


The only limitation of @ PSL's answer is that if other code changes the value A

, B

or C

in scope, it $scope.editedVar

doesn't update correctly. Instead, the next alternative uses two clockwork mechanisms to ensure that the correct scope property is kept up to date, no matter how you changed it with editedVar

input or some other code.

Forked jsFiddle

var myApp = angular.module('myApp', []);

myApp.controller('MyCtrl', function MyCtrl($scope) {
  $scope.A = 1;
  $scope.B = 2;
  $scope.C = 3;

  var propToEdit,
    deregPrevWatch;

  $scope.switchTo = function(prop) {
    propToEdit = prop;
    // set up a watch on this property so if anything else updates it 
    // editedVar gets correctly updated.
    // Make sure to deregister the previous watch first.
    if (deregPrevWatch)
      deregPrevWatch();
    deregPrevWatch = $scope.$watch(prop, function(val) {
      $scope.editedVar = val;
    });
  };

  $scope.$watch('editedVar', function(newVal, oldVal) {
    // skip the initialisation step
    if (newVal !== oldVal)
      $scope[propToEdit] = newVal;
  });

  // start off pointing at A
  $scope.switchTo('A');
});
      

p {
  margin: 2px 0;
}
      

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.7/angular.min.js"></script>

<div ng-app="myApp">
  <div ng-controller="MyCtrl">
    <p>A: {{A}}</p>
    <p>B: {{B}}</p>
    <p>C: {{C}}</p>
    <input ng-model="editedVar" />
    <p>
      <button ng-click="switchTo('A')">Switch to A</button>
      <button ng-click="switchTo('B')">Switch to B</button>
      <button ng-click="switchTo('C')">Switch to C</button>
      <button ng-click="A = 5">Set A to 5</button>
    </p>
  </div>
</div>
      

Run codeHide result


+1


source







All Articles