0

I am trying to build a custom directive for input box, which has input-model as an attribute used as ng-model. This input-model attribute is two way bound with an inner scope variable.

templateUrl:'/components/directives/inputBox.html',
transclude:true,
restrict: 'A',
scope:{
  userInput : '=inputModel'
}

Now the issue is, in the main html when I explicitly provide input-model, then it works fine. But I want a fallback when input-model is not provided, then the two way binding should be removed. The template is like

<input id="searchinput" type="search"
               name="inputBox"
               class="form-control"
               placeholder="{{placeholder}}"
               ng-model="userInput"
               ng-pattern="pattern"> 

So, when I do not provide the input-model attribute in the main html

<div input-box></div>

The binding fails as expected, giving the error :

Error: [$compile:nonassign] Expression 'undefined' used with directive 'inputBox' is non-assignable!

I want to make a fallback to avoid this scenario. How should I proceed?

Koustuv Sinha
  • 1,640
  • 19
  • 34

2 Answers2

1

Will this solution work for you?

Angular directive with default options

Community
  • 1
  • 1
Jeff Ling
  • 1,032
  • 9
  • 12
1

You can check the defined attributes in the compile method, this will allow you to handle the case before binding takes place.

    return {
    template: '<div>{{userInput}} - test</div>',
    transclude: true,
    restrict: 'A',
    scope: {
        userInput: '=inputModel'
    },
    compile: function(element, attrs, transclude) {
        if (!attrs.inputModel) {
            attrs.inputModel = 'userInput';
        }
        return {
            pre: function(scope, element, attrs) {},
            post: function(scope, element, attrs) {}
        }
    }
};

http://jsfiddle.net/anf4ryzL/

Simon Staton
  • 4,345
  • 4
  • 27
  • 49
  • Thanks! But have a question, if I use compile then I cant use link? then where to inject link function? in the post block? – Koustuv Sinha Dec 19 '14 at 10:32
  • Compile returns two methods, a pre-link and post-link these are your link functions. By default the link method used outside compile is the same as the post method so you can just use the post: function(){} in the same way as link – Simon Staton Dec 19 '14 at 10:35
  • Ok. Then when to use the pre: function() {} block if I can handle pre-binding logic in compile itself? – Koustuv Sinha Dec 19 '14 at 10:38
  • 1
    The way compile works is in 3 steps, first angular runs a directives compile function, then it runs its own compile function which will set your isolated scope (this is why we set the attribute in the compile function first), then it passes the scope, element and attributes into a pre-link method and runs these in order of parent > child then it runs the post-link methods in reverse order child > parent. This means you can A. do stuff before angular makes your scope (compile), B. do stuff before all child directives links run (pre-link), C. do stuff after child directives links (post-link) – Simon Staton Dec 19 '14 at 10:42
  • The difference between compile and pre-link/post-link is that compile has no scope yet, the isolated scope of your directive is created between compile and link – Simon Staton Dec 19 '14 at 10:43