Angularjs - creating input templates by passing variables

6

I'm trying to create a template for my inputs:

partials / input_text.html

<div>
    <input type="text" name="{{name}}" placeholder="{{placeholder}}" ng-model="model">
    <small ng-show="{{form}}.{{name}}.$dirty && {{form}}.{{name}}.$invalid" class="text-danger">Campo obrigatório</small>
</div>

directive

.directive('myModule', function() {
  return {
    restrict: 'E',
    replace: true,
    scope: {
      name: '@',
      form: '@',
      placeholder: '@',
      model: '='
    },
    templateUrl : '/partials/input_text.html'
  };
})

view.html

<form name="form">
    <my-module name="number" placeholder="Number" form="form" model="request"></my-module>
</form>

output

<form name="form">
    <div name="number" placeholder="Number" form="form" model="request" class="ng-isolate-scope">
      <input type="text" name="number" placeholder="Number" ng-model="model" required="" class="ng-dirty ng-invalid ng-invalid-required">
      <small ng-show="form.number.$dirty &amp;&amp; form.number.$invalid" class="text-danger ng-hide">Campo obrigatório</small>
    </div>
</form>

The output is correct, but should display the message "Required field" when the field is $ dirty and $ invalid, but does not show.

If I get this same output and col on the view, it works.

Any suggestions?

    
asked by anonymous 14.02.2014 / 15:30

1 answer

1

1) bindings

Although the output is correct, ie string and the corresponding DOM structure are ok, this does not mean that values attributes are being interpreted in the same way, and bindings were done in the same way as putting direct generated HTML in view.html , dispensing with directive .

Additionally, there is a serious problem: inputs are not registered in FormController . That is, an input with name "number", when included dynamically, will not be made available as%

This is so serious that there is a request opened a year ago , with about 60 votes in favor, being actively discussed to date, in order to resolve this issue.

A developer implemented a code that makes a dynamically generated input be included in FormController - people are using it as a solution until that AngularJS officially solves the problem.

Including this code that corrects the problem, your code will work, with minor adaptations.

NOTE: Others have implemented similar solutions: see here and here - as comment on GitHub , This feature will be integrated with AngularJS 1.3 - there we will no longer need to "break the branch" with workarounds as well.

Here's the complete solution ( see running on Plunkr ):

<!DOCTYPE html>
<html ng-app="app">
  <head>
    <script data-require="[email protected]" data-semver="1.2.12" src="http://code.angularjs.org/1.2.12/angular.js"></script><script>varapp=angular.module('app',[]);app.directive('myModule',function(){return{restrict:'E',replace:true,scope:{name:'@',placeholder:'@',model:'=',modelCtrl:'&'},templateUrl:'/partials/input_text.html'};});//Esteéo"workaround" mencionado:
      app.config(['$provide', function($provide) {
        $provide.decorator('ngModelDirective', function($delegate) {
          var ngModel = $delegate[0], controller = ngModel.controller;
          ngModel.controller = ['$scope', '$element', '$attrs', '$injector', function(scope, element, attrs, $injector) {
            var $interpolate = $injector.get('$interpolate');
            attrs.$set('name', $interpolate(attrs.name || '')(scope));
            $injector.invoke(controller, this, {
              '$scope': scope,
              '$element': element,
              '$attrs': attrs
            });
          }];
          return $delegate;
        });
        $provide.decorator('formDirective', function($delegate) {
          var form = $delegate[0], controller = form.controller;
          form.controller = ['$scope', '$element', '$attrs', '$injector', function(scope, element, attrs, $injector) {
            var $interpolate = $injector.get('$interpolate');
            attrs.$set('name', $interpolate(attrs.name || attrs.ngForm || '')(scope));
            $injector.invoke(controller, this, {
              '$scope': scope,
              '$element': element,
              '$attrs': attrs
            });
          }];
          return $delegate;
        });
      }]);

    </script>
  </head>
  <body>

    <script id="/partials/input_text.html" type="text/ng-template">
      <div>
          <input type="text" name="{{name}}" placeholder="{{placeholder}}" ng-model="model">
          <small ng-show="modelCtrl().$dirty" class="text-danger">Campo obrigat&oacute;rio</small>
      </div>
    </script>

    <form name="form">
        <my-module name="number" placeholder="Number" model="request" model-ctrl="form.number"></my-module>
    </form>

  </body>
</html>

2)

(Response to the question before it was edited - when it did not have the still> held because it contains relevant information.)

form.number , $dirty , and $invalid are properties of NgModel Controller

You can access these properties, within the same $error where the element containing the form attribute is, using:

  • o ng-model of name
  • o form of element where attribute name

You are trying to access it this way. However you are not using any element ng-model .

In your output , you have a form with an attribute div . However, according to the documentation, the form="form" of AngularJS directive is only enforced on elements (but not about attributes , classes or comments ).

So, for starters, you'll need a form element. Alternatively, you can use the directive form , but it is recommended for nested forms (in this case , you can use the ngForm attribute.)

// Assim não funciona. A diretiva "form" não é ativada.
<div form="myForm">
</div>

// Assim funciona. A diretiva "form" é ativada.
<form name="myForm">
</form>

// Assim a diretiva "ngForm" é ativada.
<div ng-form="myForm">
</div>

If you have already a form with ng-form being the same as you tell view.html , then fine.

// No caso abaixo, é preciso que o elemento esteja dentro de um form cujo "name" seja "myForm"!
<my-module name="number" placeholder="Number" form="myForm" model="request"></my-module>
    
14.02.2014 / 17:48