27

Is it possible to use ng-model with a component? I would like to bind a scope variable to a component with ng-model. I have plunkered my issue. I would like the component my-input to be binded to the variable from the scope userData.name.

I am using Angular JS 1.5.6 components, and want to avoid using directive.

<body ng-controller="MyCtrl">
  <div class="container">
    <h2>My form with component</h2>
    <form role="form">
      <div class="form-group">
        <label>First name</label>
        <my-input placeholder="Enter first name" ng-model="userData.name"></my-input>
      </div>
    </form>
  </div>
</body>

2 Answers 2

39

You can use this code:

function myInputController($scope) {
    var self = this;
    this.$onInit = () => {
        this.ngModel.$render = () => {
            self.model = self.ngModel.$viewValue;
        };
        $scope.$watch(function() { return self.model; }, function(value) {
            self.ngModel.$setViewValue(value);
        });
    };
}
module.component('myInput', {
    require: {
        ngModel: '^ngModel'
    },
    template: '<input ng-model="vm.model"/>',
    controller: myInputController,
    controllerAs: 'vm'
};
Sign up to request clarification or add additional context in comments.

12 Comments

I think this is a better solution for the question since it actually uses ngModel. NgModel is necessary for some use cases such as form validation.
Don't use $watch here, use this.$onChanges see docs.angularjs.org/guide/component and toddmotto.com/angular-1-5-lifecycle-hooks#onchanges for examples.
@ries isn't $onChanges triggered when binding get changed? this example don't have bindings.
@pilau you need to set attribute to component's dom: data-ng-model="your.model"
|
14

I've fixed the plunker for you.

Names of you parameters have to correspond to the names in your component. You should be using camelCased names in your component and kebab-cased in your templates. Example:

  bindings: {
      myPlaceholder: '@',
      myModel:'='
    }

 <my-input my-placeholder="Enter first name" my-model="userData.firstName">

Regarding your question about using ng-model - you can use any parameter as far you define it in your component. In this case the name of your parameter should be ngModel.

4 Comments

it work very fine thanx a lot! I would have one last question. Please, how do you to bind data when you have a form component composed with button and input components : see this new plunk
Disclaimer: because this answer is not using ngModel, form validation won't work
MISLEADING ANSWER. What you're seeing here is not a usage of ngModel but rather a binding to an attribute with the same name. This makes validations not work, and is using a two-way binding which is not supposed to be used in components.
Many people just need things to work and don't care about doing things the right way and it's a perfectly valid opinion. All in all I downvoted the answer because I consider Stackoverflow a source of knowledge, not a "ill do your homework, just copy/paste". Sorry for the rage :)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.