Michael Wilson
Michael Wilson

Reputation: 1579

Update two objects in ng-model

How could I update these scopes

$scope.name = "";
$scope.username = "";

Inside of one ng-model?

<input type="text" ng-model="name && username"/>

Update:

I am dealing with a tricky situation that I cannot use a function to the update $scope.username and i'm looking for a way to do all of this just via the ng-model attribute.

Upvotes: 2

Views: 2931

Answers (5)

gkalpak
gkalpak

Reputation: 48211

For completeness, here is one more approach: Using ngModelOptions's getterSetter:

<input ... ng-model="getSetName" ng-model-options="{getterSetter: true}" />

$scope.getSetName = function (name) {
  if (!arguments.length) return $scope.name;
  $scope.name = name;
  $scope.username = name;
};

Or a more complex example:

<input ... ng-model="user.fullname" ng-model-options="{getterSetter: true}" />

$scope.user = {
  firstname: '...',
  lastname: '...',
  fullname: function (fullname) {
    if (!arguments.length) {
      return ((this.firstname || '') + ' ' + (this.lastname || '')).trim();
    } else {
      var parts = fullname.split(' ');
      this.firstname = parts[0];
      this.lastname = parts[1];
    }
  }
};

See, also, this short demo.

Upvotes: 1

Nikos Paraskevopoulos
Nikos Paraskevopoulos

Reputation: 40298

There is a way with $parsers and $formatters. You can assume that your model is a complex object, e.g. { name: '...', surname: '...' }, edited in a single text box, e.g. everything before space is the name, everything following the first space is the surname.

A sample implementation, the HTML:

<input ng-model="data.complex" full-name="" />

And the directive:

app.directive('fullName', function() {
    return {
        restrict: 'A',
        scope: false,
        require: 'ngModel',
        link: function(scope, elem, attrs, ngModel) {
            ngModel.$parsers.unshift(function(value) {
                var tmp, result = { name: null, surname: null };
                if( value ) {
                    tmp = value.split(' ');
                    if( tmp ) {
                        if( tmp.length > 0 ) {
                            result.name = tmp.shift();
                        }
                        if( tmp.length > 0 ) {
                            result.surname = tmp.join(' ');
                        }
                    }
                }
                return result;
            });

            ngModel.$formatters.push(function(value) {
                var name, surname;
                if( value ) {
                    name = value.name;
                    surname = value.surname;
                }
                if( typeof name !== 'string' ) {
                    name = '';
                }
                if( typeof surname !== 'string' ) {
                    surname = '';
                }
                return name.length > 0 ? name + ' ' + surname : surname;
            });
        }
    };
});

See a working fiddle: http://jsfiddle.net/uL1ors7q/

Upvotes: 4

charlietfl
charlietfl

Reputation: 171690

You can only bind to one scope property with ng-model but you could add ng-change to fire a function to update the other

<input type="text" ng-model="name" ng-change="updateUsername()"/>

Controller

$scope.updateUsername = function(){
   $scope.username = $scope.name;
}

For real time updates can switch to ng-keyup

This approach is less expensive than using a watch since it doesn't have to be constantly monitored and only fires on demand

Upvotes: 1

MBielski
MBielski

Reputation: 6620

Angular two-way data binding will take care of this for you. No need to monitor change events or anything else.

In you page:

<input type="text" ng-model="name" />

In your controller:

$scope.username = $scope.name;

Upvotes: -2

hoeni
hoeni

Reputation: 3290

You could use a AngularJS watcher for upding the other value:

<input type="text" ng-model="name"/>

And in the controller:

$scope.$watch('name', function(name){
  $scope.username = name;
});

Upvotes: 2

Related Questions