Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

how to pass a json as a string param to a directive

Tags:

angularjs

When I try to eval the below json form it gives me an error -

eval("{form: 'form' , nameToMatch: 'password1'}")

Why is the above form not valid ?

However the below works fine -

eval("{form: 'form'}")

I am trying to pass the above json as a string, as a param input to a directive.

Below is the html -

<input type="password" name="password2" ng-model="user.confirmPassword" placeholder="Confirm Password" match="{form: 'form', nameToMatch: 'password1'}" required="required"/>

Thanks, Murtaza

like image 316
murtaza52 Avatar asked Feb 04 '13 13:02

murtaza52


4 Answers

Put parens around your json:

 eval("({form: 'form' , nameToMatch: 'password1'})")

Doesn't seem like an angular question though. Not sure what you're trying to do:

Anyhow, to pass the json to the directive there are lots of ways to do that. I'm not sure why you'd want to do that and not just pass an object though.

passing json can be done a lot of ways...

  1. From your attributes object:

    app.directive('foo', function () {
       return function(scope, element, attrs) {
           var obj = eval('(' + attrs.foo + ')');
       };
    });
    

    where

    <div foo="{'test':'wee'}"></div>
    
  2. From an isolated scope:

    app.directive('foo', function () {
       return {
         restrict: 'E',
         scope: {
          'jsonIn' : '@'
         },
         link: function(scope, element, attrs) {
           var obj = eval('(' + scope.jsonIn + ')');
         };
       };
    });
    

    where

    <foo json-in="{'test':'wee'}"></foo>
    

But it's by far better to avoid using the native eval at all costs, if you can. Which in almost all cases you can. If you have some data just put it in an object on a scoped parameter and pass it in either via a two-way property on an isolated scope, or by name and do an angular $eval on it.

EDIT: The pass an object in...

You could use two way binding on an isolated scope:

app.directive('foo', function (){
  return {
     restrict: 'E',
     scope: {
        'data' : '='
     },
     link: function(scope, elem, attrs) {
        console.log(scope.data);
     }
  };
});

where

<foo data="{ test: 'wee' }"></foo>

The really cool thing about doing it this way, is if you're using a scoped property it will update bi-directionally:

app.controller('MainCtrl', function($scope) {
    $scope.bar = { id: 123, name: 'Bob' };
});

where

<foo data="bar"></foo>

I hope that helps.

like image 142
Ben Lesh Avatar answered Sep 21 '22 02:09

Ben Lesh


It looks like you are trying to confirm a password in a form. There are many ways that you can go about this without resorting to JSON to pass values around in AngularJS. The most useful resource I've found online is from this Google Group thread:

1) http://jsfiddle.net/pkozlowski_opensource/GcxuT/23/ will compare value in a second field with model value of the first field

2) http://jsfiddle.net/S8TYF/ will compare value in a second field with input value of the first field

The difference might be subtle but has practical consequences: with (2) the confirm validation will kick-in as soon as you start typing anything in the first field. With (1) the confirm validation will kick-in only after the first field is valid. In the e-mail confirm example it means that you won't start showing confirmation errors till e-mail validation errors are sorted out (so a user can focus on one error at the time).

Source: https://groups.google.com/d/msg/angular/R4QeNsNksdY/migbplv8GxIJ

From the first link, the directive is used as follows:

<label>e-mail</label>
<input name="email" type="email" required ng-model="email">  

<label>repeat e-mail</label>
<input name="emailRepeat" type="email" required 
       ng-model="emailRepeat" 
       ui-validate-equals="email">

Where the ui-validate-equals directive points to the email model that was defined in the first input.

There are some StackOverflow answers to this if you would like to look there as well for additional ideas to solve your problem.

like image 40
Jay Avatar answered Sep 23 '22 02:09

Jay


See also. @Blesh has mentioned in passing, but not emphasized: Angular provides you with a 'safe'-ish version of eval(), which works perfectly for passing declarative objects/arrays into your directive if you don't want to declare them on your scope, and wisely don't want to use native eval(). In the OP's example, just use this inside the directive:

angular.$eval(attrs.match);
like image 25
XML Avatar answered Sep 20 '22 02:09

XML


Doesn't seem like an angular question though.

Agreed - vanilla JS can handle this just fine.

// Markup (HTML)
<div mydirective='{"test1": "foo", "test2": "bar"}'></div>

// App (JS)
JSON.parse(attrs['mydirective']);
like image 27
Ben Avatar answered Sep 19 '22 02:09

Ben