Sophie McCarrell
Sophie McCarrell

Reputation: 2871

Angular directive attributes aren't being passed through

I'm trying to shorten my form code by making directives for each element, however my directive is displaying none of what I'm passing to it and the model isn't being bound.

HTML:

<formstring dataBinding="project.title" dataTitle="Title" dataPlaceholder="title" />

directive:

app.directive('formstring', function () {
  return {
    restrict: 'AEC',
    dataBinding: '=',
    dataTitle: '@dataTitle',
    dataPlaceholder: '@dataPlaceholder',
    dataHelp: '@dataHelp',
    templateUrl: '/app/js/directives/form/string.html',
  };
});

string.html:

<div class="form-group">  2   <label for="{{dataTitle}}" class="col-sm-2 control-label">{{dataTitle}}</label    >
  <div class="col-sm-10">
    <input type="text" class="form-control" id="{{dataTitle}}" placeholder="{{da    taPlaceholder}}" ng-model="dataBinding">
    <p ng-show="dataHelp" class="help-block">{{dataHelp}}</p>
  </div>
</div>

project is a $scope object that has an attribute 'title'.

What am I missing? Why does this show up at a blank input with none of the attributes filled in and why does the binding not work?

Upvotes: 1

Views: 1079

Answers (3)

Jim Schubert
Jim Schubert

Reputation: 20357

You need to change how you're creating isolate scope:

app.directive('formstring', function () {
  return {
    restrict: 'AEC',
    scope: {
       dataBinding: '=',
       dataTitle: '@dataTitle',
       dataPlaceholder: '@dataPlaceholder',
       dataHelp: '@dataHelp'
    },
    templateUrl: '/app/js/directives/form/string.html',
  };
});

Read the doc for details about what an isolate/isolated scope means because it has an effect on the overall scope.

edit: I didn't notice this additional issue before. Your camel case scope properties become snake cased when you use your directive (see Mobin's answer):

<formstring data-binding="project.title" data-title="Title" data-placeholder="title" />

In your template, however, the properties are still camel cased as you have:

<div class="form-group">  2   <label for="{{dataTitle}}" class="col-sm-2 control-label">{{dataTitle}}</label    >
  <div class="col-sm-10">
    <input type="text" class="form-control" id="{{dataTitle}}" placeholder="{{da    taPlaceholder}}" ng-model="dataBinding">
    <p ng-show="dataHelp" class="help-block">{{dataHelp}}</p>
  </div>
</div>

This is because the bindings in your template are JSON properties, whereas the attributes when you use your directive's properties are XML properties.

There are minor tweaks I'd apply to your template, for instance id="{{dataTitle}}" can easily break HTML standards that require the id attribute is unique... you probably want to use name="{{dataTitle}}" instead. name could still cause issues, but it wont' break document.getElementById for example.

Also, I'd use ng-bind whenever possible:

<p ng-show="dataHelp" class="help-block" ng-bind="dataHelp"></p>

Upvotes: 2

GregL
GregL

Reputation: 38103

You haven't understood how directives are configured correctly. I suggest you read the documentation, it may help you understand better.

In the meantime, here is what your HTML, directive code and template should look like (there is also a working demonstration on Plunkr):

HTML:

<formstring data-binding="project.title" 
            data-title="Title Demo" 
            data-placeholder="title placeholder"
            data-help="My help text">
</formstring>

directive:

app.directive('formstring', function () {
  return {
    restrict: 'E',
    scope: {
        binding: '=',
        title: '@',
        placeholder: '@',
        help: '@'
    },
    templateUrl: '/app/js/directives/form/string.html',
  };
});

Template (string.html):

<div class="form-group">
   <label for="{{title}}" class="col-sm-2 control-label">
      {{title}}
    </label>
    <div class="col-sm-10">
      <input type="text" class="form-control" id="{{title}}" placeholder="{{placeholder}}" ng-model="binding">
      <p ng-show="help" class="help-block">{{help}}</p>
    </div>
</div>

Upvotes: 2

Mobin Skariya
Mobin Skariya

Reputation: 392

It should be

<formstring data-binding="project.title" data-title="Title" data-placeholder="title" />

.

Upvotes: 1

Related Questions