0

In the following AngularJS code, when you type stuff into the input field, I was expecting the div below the input to update with what is typed in, but it doesn't. Any reason why?:

html

<div ng-app="myApp">
    <input type="text" ng-model="city" placeholder="Enter a city"  />
    <div ng-sparkline ng-model="city" ></div>
</div>

javascript

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

app.directive('ngSparkline', function () {
    return {
        restrict: 'A',
        require: '^ngModel',
        template: '<div class="sparkline"><h4>Weather for {{ngModel}}</h4></div>'
    }
});

http://jsfiddle.net/AndroidDev/vT6tQ/12/

1
  • Your directive isn't changing the value of the ngModel there for you don't need to set ng-model="city" on your directive, I'd look at @drew_w 's example below and set the ng-sparkline attribute with the value of city Commented Jun 12, 2014 at 16:10

5 Answers 5

1

Add ngModel to the scope as mentioned below -

app.directive('ngSparkline', function () {
    return {
        restrict: 'A',
        require: '^ngModel',
        scope: {
            ngModel: '='
        },
        template: '<div class="sparkline"><h4>Weather for {{ngModel}}</h4></div>'
    }
});

Updated Fiddle

Sign up to request clarification or add additional context in comments.

1 Comment

I copied the tutorial code from ng-newsletter.com/posts/directives.html and the sample I copied it from didn't have the scope parameter added although the sample following it did. I read what they posted about why scope is required but it doesn't make sense. Can you explain why it's needed in order for the typed text to show? Thanks a million.
1

It should be

template: '<div class="sparkline"><h4>Weather for {{city}}</h4></div>'

since you are binding the model to city

JSFiddle

Comments

1

The basic issue with this code is you aren't sharing "ngModel" with the directive (which creates a new scope). That said, this could be easier to read by using the attributes and link function. Making these changes I ended up with:

HTML

<div ng-sparkline="city" ></div>

Javascript

app.directive('ngSparkline', function ($compile) {
    return {
        restrict: 'A',
        link: function (scope, element, attrs) {
            var newElement = '<div class="sparkline"><h4>Weather for {{' + attrs.ngSparkline + '}}</h4></div>';
            element.append(angular.element($compile(newElement)(scope)));
        }
    }
});

Using this pattern you can include any dynamic html or angular code you want in your directive and it will be compiled with the $compile service. That means you don't need to use the scope property - variables are inherited "automatically"!

Hope that helps!

See the fiddle: http://jsfiddle.net/8RVYD/1/

Comments

0
template: '<div class="sparkline"><h4>Weather for {{city}}</h4></div>'

Comments

0

the issue is that require option means that ngSparkline directive expects ngModel directive controller as its link function 4th parameter. your directive can be modified like this:

app.directive('ngSparkline', function () {
    return {
        restrict: 'A',
        require: '^ngModel',
        template: '<div class="sparkline"><h4>Weather for {{someModel}}</h4></div>',
        link: function(scope, element, attrs, controller) {
            controller.$render = function() {
                scope.someModel = controller.$viewValue;
            }
        }
    }
});

but this creates someModel variable in scope. that I think isn't necessary for this use case.

fiddle

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.