1

When I populate an input field from within a directive, it shows on the DOM, but $scope is not capturing the value. How do I fix it so that $scope captures the new info?

How to reproduce the behaviour from my Fiddle:

Click Fill with Directive
Click Log
--> $scope.input val is undefined

Fill input with 'asdf'
Click Log
--> $scope.input val is 'asdf'

Fill input with 'abcd'
Click Fill with Directive
--> DOM shows 'quick brown fox'
Click Log
--> $scope.input val is 'abcd'

My code is here: JSFiddle

JS:

'use strict';

var app = angular.module('myApp', []);

app.controller('myCtrl', function($scope){
    $scope.logResult = function(){
        console.log($scope.input);
    }
});

app.directive('fillInput', function(){
    return {
        link: function($scope, elem){
            $scope.fillFormDirective = function() {
                console.log(elem);
                elem.val('quick brown fox');
            }        
        }
    };
});

HTML:

<div ng-controller='myCtrl'>

    <div>
        <input type="text" ng-model="input.weird" id="inputField" fill-input />
    </div>

    <div>
        <button ng-click="fillFormDirective()" >Fill With Directive</button>
    </div>   

    <div>
        <button ng-click="logResult()">Log Result</button>
    </div>

</div> 
Ryan W Kan
  • 380
  • 3
  • 16

2 Answers2

1

There is a problem with the code you posted:

In your link function your scope should be scope NOT $scope. If you want 2 way binding between you controller and the directive, you need to pass in a variable through an isolate scope. However with an isolate scope the fillFormDirective() method won't be called if it is declared on elements that don't have the fill-input directive on them.

Try this:

app.directive('fillInput', function(){
    return {
        scope:{
           fillInput:'='
        }
        link: function(scope, elem){
              elem.val(scope.fillInput);
              elem.bind("click", function(e){
                console.log(elem);
                elem.val('quick brown fox');              
              });
        }
    };
});

And your HTML:

<input type="button" fill-input="text" /> See working plunk.

EDIT I've updated the plunk to not make use of an isolate scope.

Mohammad Sepahvand
  • 17,364
  • 22
  • 81
  • 122
  • `fillFormDirective` is accessible for every directive that has access to the same scope as `fillInput`. – a better oliver Apr 20 '14 at 08:09
  • @zeroflagL Yep thanks for the correction. I've updated my answer. I actually didn't know that. I was also assuming that the OP wanted 2 way binding between the controller and the directive, but yea, in the context of an isolate scope `fillFormDirective` won't be accessible to other elements. Thanks. – Mohammad Sepahvand Apr 20 '14 at 09:41
  • @MohammadSepahvand It still does not work. I've updated your plunkr here: http://plnkr.co/edit/XH9VF4aJsUYKtJTzN2DL?p=preview . Notice that updating input with a directive does not trigger ngModel, so console logs undefined. If you manually type something into the field, it logs appropriately. – Ryan W Kan Apr 20 '14 at 12:16
  • @RyanWKan Inside `fillFormDirective` you should be logging `scope.text`, not `scope.input`. – Mohammad Sepahvand Apr 20 '14 at 12:31
  • @RyanWKan, sorry im a bit confused now, just in one sentence, tell me exactly what it is you're trying to do. – Mohammad Sepahvand Apr 20 '14 at 12:33
1

Solution from this SO thread:

Update Angular model after setting input value with jQuery

Working Plunkr: http://plnkr.co/edit/QKDaHT3CllyBtrRPdYUr?p=preview

Basically, quoting @Stewie,

ngModel listens for "input" event, so to "fix" your code you'd need to trigger that event after setting the value:

      elem.bind("click", function(e){
        console.log(elem);

        newElem.val('quick brown fox');
        newElem.triggerHandler('input'); <-----This line of code fixed the problem
      });
Community
  • 1
  • 1
Ryan W Kan
  • 380
  • 3
  • 16