0

I am using the html element to call a template that contains inputs. This gets used several times on the page. How can I differentiate between them using an attribute and/or index, to populate each respective ng-model?

JS Code:

angular.module('myModule').directive('address', function () {
  return{
    restrict: 'E',
    replace: true,
    templateUrl: '/address.tpl.html',
    scope: {
      address: '=',
      form: '='
    },
    link: function (scope, el, attrs) {
      scope.isRequired = attrs.optional === undefined;
    }
  };
});

Main page HTML code:

<p>My Address</p>      <address></address>
<p>Extra Address 1</p> <address></address>
<p>Extra Address 2</p> <address></address>
<p>Your Address</p>    <address></address>

There can be any number of extra addresses.

Address.tpl.html HTML code:

  <ng-form name="addressForm">
    <label>Postcode:</label> 
    <input name="postcode" type="text" ng-model="address.postcode"/>
  </ng-form>

Obviously, this doesn't help me get to the values, as each instance of the input will have the same ng-model: $scope.address.postcode. Ideally, I am looking to put an attribute in the address element that will mean I can define the name of the ng-model as address.myAddress.postcode or address.extraAddress6.postcode.

EDIT: Now that I have the answer, I've noticed that the necessary code is already in the JS file. That address: '=' was the data-binding I needed.

Main page HTML code (New code):

<p>My Address</p>      <address address="my"></address>
<p>Extra Address 1</p> <address address="extra1"></address>
<p>Extra Address 2</p> <address address="extra2"></address>
<p>Your Address</p>    <address address="your"></address>

I can now access the scope value of ng-model="address.postcode" using $scope.my.postcode and $scope.extra1.postcode, etc etc.

3 Answers 3

1

Can you add an atrribute to each address tag and use that to differentiate them?

    <p>My Address</p>      <address type="'my'"></address>
    <p>Extra Address 1</p> <address type="'extra1'"></address>
    <p>Extra Address 2</p> <address type="'extra2'"></address>
    <p>Your Address</p>    <address type="'your'"></address>

scope: {
      address: '=',
      form: '=',
      type: '&'

    },
    link: function (scope, el, attrs) {
      scope.isRequired = attrs.optional === undefined;
      switch(attrs.type) {
          case 'my':
          ...
Sign up to request clarification or add additional context in comments.

4 Comments

Hi imcg, that's what I'm trying to do. I want to add an attribute that gets used as the ng-model. Eg: <address data="myAddress"></address> would be replaced with <input name="postcode" type="text" ng-model="myAddress.postcode"/> and <address data="yourAddress"></address> would be replaced with <input name="postcode" type="text" ng-model="yourAddress.postcode"/>.
Ok so if I understand you correctly I think you need to add the data attribute (<address data="myAddress">) as you suggest, create a data:'=' binding in your directive's scope, and use ng-model="data.postcode" in your template.
That sounds like it might work. Thank you. I'll be sure to give that a try in the morning.
Ha! Yup, that was the one. Note to others: even though each postcode input still has the same ng-model="data.postcode" in the markup, in fact AngularJS knows each one is really ng-model="my.postcode", ng-model="extra1.postcode", ng-model="extra2.postcode", ng-model="your.postcode".
0

You could use ng-repeat in this instance. It sounds like you want an arbitrary amount of extra addresses. So maybe this will help:

$scope.extraAddresses = [ 'address1', 'address2', 'address3', 'address4' ];

Then in your HTML:

<p ng-repeat="address in extraAddresses">{{address}}</p>

If you want the addresses to contain extra data. Update the model to be an array of objects:

$scope.extraAddresses = [ 
   {
      "address": "address1",
      "postalcode": "06060"
   }
];

Then in your HTML:

<p ng-repeat="address in extraAddresses">{{address.address}}, {{address.postalcode}}</p>

In other words, basically treat everything as an array of objects and iterate through them using ng-repeat.

1 Comment

Hi, jrthib. Sorry, I'm not using ng-repeat. I'm using a directive. There's no array to loop through. I'm just calling a template as-and-when I need it.
0

If I were you, I would start by putting all of your initialization data into a single JSON object. Perhaps you could have:

ADDRESS_JSON_OBJECT = [
    { address1: "1234 Fake St.", country: "Blahnada" },
    { address1: "1234 Fake St.", country: "Blahmerica" }
];

In your application module define a 'value' like so:

myApplication = angular.module( ... ).value('addresses', ADDRESS_JSON_OBJECT)

Your address controller will now depend on this data:

myControllerModule = 
    angular.module( ... )
    .controller('AddressController', 
        ['$scope', 'addresses', function ($scope, addresses) {
        //don't do the init here....
        }
    );

Now in each of your HTML templates you can init the values using the 'ng-init' predicate:

<ng-form name="addressForm">
    <label>Postcode:</label> 
    <input ng-init="address = addresses[0]" name="postcode" type="text" ng-model="address.postcode"/>
</ng-form>

I haven't actually tested this code, but I believe this general idea would work. I've used the ng-init to bootstrap inputs before.

4 Comments

Hi Brendan, I'm not trying to initialise any data, I just want to set the property of the ng-model attribute of the <input> based on the attribute I put into the <address> element. E.g. <address data="myAddress"></address>. The ng-model for the <input> should now be ng-model="myAddress". Apologies if I've read your code wrong.
I think you misunderstand me. I want to set the ng-model attribute of the input, not its value.
You could likely restructure your code. If you're really intent on having inconsistent attribute names then maybe this answer will interest you: stackoverflow.com/questions/15597228/…
That's more like it. Thank you Brendan. That link goes to a question that is effectively what I am asking. Cheers! :)

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.