I have the code below. predictions['Team1 expected goals'] comes up as undefined in the donutChart.js directive even though the value is defined on the second line. How do I properly pass that to the directive?
<div>
<div>{{ (fixture.team1.name.short_name || fixture.team1.name.gsm_name) }}</div>
<div>{{ predictions['Team1 expected goals'] | number : 2 }}</div>
</div>
<div>
<donut-chart team1="predictions['Team1 expected goals']"
team2="predictions['Team2 expected goals']">
</donut-chart>
</div>
The below works as expected:
<donut-chart team1="1.26" team2="0.81"></donut-chart>
Here is the code for the donutChart.js directive. Note also that the structure is, an overall controller calls a directive (called models-prices) which calls this chart directive.
angular.module('stratabet')
.directive('donutChart', function(appVersion) {
'use strict';
var directive = {
priority: 0,
restrict: 'E',
scope: {
team1: '=',
team2: '='
},
controller: function($scope) {
console.log('donutChart controller - team1: ' + $scope.team1 + ', team2: ' + $scope.team2);
},
link: function(scope, element, attrs) {
console.log('donutChart - team1: ' + scope.tea1 + ', team2: ' + scope.team2);
}
}
In the line,
console.log('donutChart - team1: ' + scope.tea1 + ', team2: ' + scope.team2);
there is a typo in scope.tea1, it should be $scope.team1 as there is no property tea1 on scope
it should be
console.log('donutChart - team1: ' + scope.team1 + ', team2: ' + scope.team2);
Related
I have a directive that looks something like the following:
.directive('textInput', function() {
return {
restrict: 'E',
replace: true,
transclude: false,
compile: function(element, attrs) {
var html =
'<div class="form-group">' +
'<label>{{ \'' + attrs.label + '\' | translate }}</label>' +
'<input type="text" class="form-control input-sm" placeholder="' + attrs.placeholder +
'" ng-model="' + attrs.ngModel + '"' + attrs.directives + '>' +
'</div>';
var newElem = $(html);
element.replaceWith(newElem);
return function (scope, element, attrs, controller) { };
}
};
})
Note that the directives attribute was a string that added additional attribute information (e.g. tooltip info)
I have converted it to a 1.5 component but I'm not able to do the same with the directives definition.
.component('textInput', {
bindings: {
label: '#',
placeholder: '#',
directives: '<',
ngModel: '='
},
require: {
ngModelCtrl: 'ngModel'
},
template:
'<div class="form-group">' +
'<label ng-if="$ctrl.label">{{$ctrl.label | translate }}</label>' +
'<input' +
' type="text"' +
' class="form-control input-sm"' +
' placeholder="{{$ctrl.placeholder}}"' +
' ng-model="$ctrl.ngModel"' +
' {{$ctrl.directives}}>' +
'</div>'
})
<text-input directives="tooltip='foobar'"></text-input>
How can I pass in a string to the <text-input/> element such that the underlying template gets the correct information?
It is not possible, according to the docs,:
When not to use Components:
for directives that rely on DOM manipulation, adding event listeners
etc, because the compile and link functions are unavailable when you
need advanced directive definition options like priority, terminal,
multi-element when you want a directive that is triggered by an
attribute or CSS class, rather than an element
and in the same page it says that components doesn't have compile function.
I have one module call "menuLeft", when module he initiate ,not loading correctly my directive, but if run my function en el method "run" correctly.
I dont know why is this.
This is my code
(function () {
angular.module('menuLeft', []);
angular.module('menuLeft')
.run(htmlMenuDirectivaGrupo)
.directive('ctrlMenuDirectivaGrupo', ctrlMenuDirectivaGrupo);
//MY MENU DIRECTIVE (THIS NOT LOAD)
//MENU GRUPO
/**
* #ngInject
*/
function ctrlMenuDirectivaGrupo($timeout) {
alert('hello ctrlmenu');
return {
scope: {
section: '='
},
templateUrl: 'partials/menuToogle.tmpl.html',
link: function ($scope, $element) {
var controller = $element.parent().controller();
$scope.isOpen = function () {
return controller.isOpen($scope.section);
};
$scope.toggle = function () {
controller.toggleOpen($scope.section);
};
}
};
}
//MY TEMPLATE FOR DIRECTIVE (THIS IF LOAD)
/**
* #ngInject
*/
function htmlMenuDirectivaGrupo($templateCache) {
alert('hello htmlmenu');
$templateCache.put('partials/menuToogle.tmpl.html',
'<md-button class="md-button-toggle"\n' +
' ng-click="toggle()"\n' +
' aria-controls="docs-menu-{{section.name | nospace}}"\n' +
' flex layout="row"\n' +
' aria-expanded="{{isOpen()}}">\n' +
' {{section.name}}\n' +
' <span aria-hidden="true" class=" pull-right fa fa-chevron-down md-toggle-icon"\n' +
' ng-class="{\'toggled\' : isOpen()}"></span>\n' +
'</md-button>\n' +
'<ul ng-show="isOpen()" id="docs-menu-{{section.name | nospace}}" class="menu-toggle-list">\n' +
' <li ng-repeat="page in section.pages">\n' +
' <menu-link section="page"></menu-link>\n' +
' </li>\n' +
'</ul>\n' +
'');
}
})();
Why not load two functions?, there are bad code or declarations?
thanks.
Use something like this . .
return {
restrict: 'E',
scope: {
section: '='
},
controller: ['$scope', function ($scope){..}],
link: function (scope, element, attrs) {..},
template: '<div class="bootsrtap">'+
'<input type="text" ng-model="searchParam" placeholder="{{ attrs.placeholder }}"'+
'class="{{ attrs.inputclass }}"'+
'id="{{ attrs.inputid }}"'+
'ng-required="{{ autocompleteRequired }}" />'+
'</div> '
};
the problem is , what my directive nor declaring correctly in .html
This is the way we should call it to function properly.
DIRECTIVES
(function () {
angular.module('menuLeft', []);
angular.module('menuLeft')
.run(htmlMenuDirectivaGrupo)
.directive('menuGrupo', ctrlMenuDirectivaGrupo);
//MY MENU DIRECTIVE (THIS NOT LOAD)
//MENU GRUPO
/**
* #ngInject
*/
function ctrlMenuDirectivaGrupo($timeout) {
alert('hello ctrlmenu');
return {
scope: {
section: '='
},
templateUrl: 'partials/menuToogle.tmpl.html',
link: function ($scope, $element) {
var controller = $element.parent().controller();
$scope.isOpen = function () {
return controller.isOpen($scope.section);
};
$scope.toggle = function () {
controller.toggleOpen($scope.section);
};
}
};
}
//MY TEMPLATE FOR DIRECTIVE (THIS IF LOAD)
/**
* #ngInject
*/
function htmlMenuDirectivaGrupo($templateCache) {
alert('hello htmlmenu');
$templateCache.put('partials/menuToogle.tmpl.html',
'<md-button class="md-button-toggle"\n' +
' ng-click="toggle()"\n' +
' aria-controls="docs-menu-{{section.name | nospace}}"\n' +
' flex layout="row"\n' +
' aria-expanded="{{isOpen()}}">\n' +
' {{section.name}}\n' +
' <span aria-hidden="true" class=" pull-right fa fa-chevron-down md-toggle-icon"\n' +
' ng-class="{\'toggled\' : isOpen()}"></span>\n' +
'</md-button>\n' +
'<ul ng-show="isOpen()" id="docs-menu-{{section.name | nospace}}" class="menu-toggle-list">\n' +
' <li ng-repeat="page in section.pages">\n' +
' <menu-link section="page"></menu-link>\n' +
' </li>\n' +
'</ul>\n' +
'');
}
})();
HTML
<menu-grupo></menu-grupo>
I recommend reading https://github.com/johnpapa/angular-styleguide
Thanks for all.
Hi I have created a directive for toggle button.
DIRECTIVE
app.directive('toggleBtn',[function () {
return {
restrict: 'EA',
replace: true,
require: ['name', '^ngModel'],
scope: {
isDisabled: '=',
name: '#',
ngModel: '='
},
template:
' <div class="toggle-switch on off"> ' +
' <input ng-model="ngModel" id="{{name}}" type="checkbox" ng-disabled="{{isDisabled}}" ' +
' hidden=""><label for="{{name}}" ' +
' class="ts-helper"></label> ' +
' </div> '
};
}]);
HTML
<input ng-model="sample1" name="sample1"
type="checkbox" class="someclass" ng-change="doSomething()" toggle-btn>
Directive is working fine, except ng-change. ng-change attribute is added to div, not to input-checkbox.
How to add those attributes to input-checkbox?
Not just ng-change, there can be other attributes also. Like ng-focus, title, ng-click, etc... (ng-click and title will work as it will append to main div, I'm just giving an example here).
Plunkr Demo here
Change your code to this
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
$scope.doSomething = function() {
console.log("Do something");
}
});
app.directive('toggleBtn', [function() {
return {
restrict: 'EA',
replace: true,
require: ['name', '^ngModel'],
scope: {
isDisabled: '=',
name: '#',
ngModel: '=',
ngChange: '&'
},
template: ' <div class="toggle-switch on off"> ' +
' <input ng-model="ngModel" id="{{name}}" type="checkbox" ng-change="ngChange()" ng-disabled="{{isDisabled}}" ' +
' hidden=""><label for="{{name}}" ' +
' class="ts-helper"></label> ' +
' </div> '
};
}]);
Demo
I am trying to compile HTML String directive which is place inside foreach loop. I even tried putting scope but still not working. My sample code looks like this:
hotelierApp.directive('maps', ['$translate', '$filter', '$compile',
function ($translate, $filter, $compile) {
return {
restrict: "A",
replace: true,
scope: true,
link: function (scope, element, attrs) {
_.each(scope.properties, function (property) {
var strHtml = $compile('<div><div class=\'hotelMarker\'>' +
'<div class=\'hotelIcon\'>' +
'<img alt=\'\' class=\'menuShadow\' src=\'{{PropertyThumbnail}}\' height=\'45\' width=\'45\'/>' +
'</div>' +
'<div class=\'hotelText\'>' +
'<span class=\'hotelHeader\'>{{PropertyName}} ' +
'</span>' +
'</div>' +
'</div></div>')(property);
return function () {
if (infoWindow) {
infoWindow.close();
}
infoWindow.setContent(strHtml[0].innerHTML);
infoWindow.open(map, markerOtherHotel, strHtml[0].innerHTML);
}
})(markerOtherHotel, property.PropertyID));
});
},
template: ''
}}]);
Please help
property is not a scope object and cannot be used with $compile in this way. Instead, you could do something like this:
var strHtml = $compile('<div><div class=\'hotelMarker\'>' +
'<div class=\'hotelIcon\'>' +
'<img alt=\'\' class=\'menuShadow\' src=\'' + property.PropertyThumbnail + '\'' +
' height=\'45\' width=\'45\'/>' +
'</div>' +
'<div class=\'hotelText\'>' +
'<span class=\'hotelHeader\'>' + property.PropertyName + ' ' +
'</span>' +
'</div>' +
'</div></div>')(scope);
See this Plunker for a working example.
I have html:
<div ng-repeat="mydata in data" class="ng-scope ng-binding">
<p class="ng-binding">{{mydata.postdata}}</p>
<div my-rating rating-value="rating" data-cat="post" data-id="mydata.id" ></div>
<div ng-repeat="childData in mydata.personRelatedData">
{{childData.personName}}
<div my-rating rating-value="rating" data-cat="person" data-id="childData .id" >
</div>
</div>
I have a Directive :
myDirectives.directive('myRating', function () {
return {
restrict: 'A',
template: '<div><ul>' +
'<li ng-repeat="i in getNumber(myNumber)" ng-click="toggle($index)" id=$index>' +
'<div ng-switch="switchPoint<$index">'+
'<div ng-switch-when=true><img ng-src="img/{{Unrated}}"></div>'+
'<div ng-switch-when=false><img ng-src="img/{{Rated}}"></div>'+
' </div>' +
'</li></ul></div>',
scope: {
ratingValue: '=',
dataCat: '=',
dataId: '=',
readonly: '#',
onRatingSelected: '&'
},
link: function (scope, elem, attrs) {
scope.toggle= function(val) {
scope.ratingValue = val + 1;
scope.onRatingSelected({rating: null});
scope.switchPoint = val;
}
}
}
Currently i have implemented that on page load, the rating from the db comes, and while rendering the template, if rating for that ID exists, then it is rated on the isolated rating template too.
Now what I want is that on click of a rating, the execution should rate that ID celebrity, but also loop the other isolated templates, to see if ratings for that ID exist.. and if so, we can update their rating too.
How can I loop the other isolated templates on click of one?
Don't store the rating value in the scope of the directive, store the rating in a location that is accessible to all of the items.
mydata is a perfect location for this. Instead of passing the mydata.rating property directly to the directive (and thus passing a value), pass the whole mydata object, and reference the mydata.rating property within the directive. Since you're passing an object to the directive, it will be a reference, not a value, i.e. all of the directives which are passed the same mydata object will be looking at the same object, not copies of a particular property. You could achieve the same goal by making the rating property an object as well instead of a value.
EDIT: in response to comments, you could change it to be more direct.
myDirectives.directive('myRating', function () {
return {
restrict: 'A',
template: '<div><ul>' +
'<li ng-click="setRating(1)">' +
' <img ng-src="img/{{ myData.rating >= 1 ? Unrated : Rated}}">' +
'</li>' +
'<li ng-click="setRating(2)">' +
' <img ng-src="img/{{ myData.rating >= 2 ? Unrated : Rated}}">' +
'</li>' +
'<li ng-click="setRating(3)">' +
' <img ng-src="img/{{ myData.rating >= 3 ? Unrated : Rated}}">' +
'</li>' +
'<li ng-click="setRating(4)">' +
' <img ng-src="img/{{ myData.rating >= 4 ? Unrated : Rated}}">' +
'</li>' +
'<li ng-click="setRating(5)">' +
' <img ng-src="img/{{ myData.rating >= 5 ? Unrated : Rated}}">' +
'</li>' +
'</ul></div>',
scope: {
myData: '=',
readonly: '#',
onRatingSelected: '&'
},
link: function (scope, elem, attrs) {
scope.setRating = function(val) {
scope.myData.rating = val;
scope.onRatingSelected(scope.myData);
}
}
}
I don't expect this example to work with just copy/paste to your problem; it's just meant as an idea to get your rolling.