attribute value in directive angularjs - angularjs

i have html markup that i need to use at many places so rather to copy paste it again and again but with different Headings
i thought to create a directive it looks like this
myModule.directive('row', function ($compile) {
return {
restrict: 'E',
template: '<div class="row">'+
'<div class="col-md-10 margin-top-10px font-18px">{{heading}}</div>'+
' <div class="col-md-2">'+
'<div class="margin-top-10px"><span ng-click="close()" class="close helvetica color-black">×</span></div>'+
'</div>'+
'</div>',
replace: true,
link: function (scope, element, attrs, ctrl) {
var test = attrs.heading;
}
};
});
and how i m trying to use it
<row heading="its my heading "></row>
i cant make it work .i dont want to create isolated scope or child scope i just wanted to pass value from attribute and when template gets replaced i want its interpolated value .
can some one help me how can id o this

Try with:
link: function (scope, element, attrs, ctrl) {
scope.heading = attrs.heading;
}
It might also be a good idea to set
scope: true
You have to actually attach the value from the attr object to the scope before it can be used in the template.

add
scope: {
heading: '='
}
to your directive's definition to create 2 way data-binding with that attribute. you would do this if you are passing in a scope variable.
or use #
scope: {
heading: '#'
}
if you are just passing in a string.
minimalist plunkr to demonstrate: http://plnkr.co/edit/U5OzlMiXaIsHEdb5gmRT

Related

AngularJS directive that sets its own tag name to a defined string

I want to have a tag like <h1> that I can pass the level as an attribute (for nested templates to pass the depth).
This could look like:
.directive('hx', function() {
return {
restrict: 'E', transclude: true, replace: true,
link: function(scope, element, attrs) {
this.template = '<h' + attrs.level + ' ng-transclude></h' + scope.level + '>'
}
}
})
This approach does not work as expected as you can see at http://plnkr.co/edit/tt1oJySS4j0FmamEYBEr?p=preview
You can set a template on a directive. Each time the link function runs, you are changing the template. The first <hx> element in your code has no template, so nothing appears. The second will use the template from the first (h1) and the third will use the template from the second (h1 again).
Instead, you want to use the transclude function for directives:
link: function(scope, element, attrs, ctrl, transclude) {
transclude(scope, function (clone) {
const header = angular.element('<h' + attrs.level + '></h' + attrs.level + '>');
header.append(clone);
element.append(header);
// element.replaceWith(header); // variant replace=true
});
}
This gives you access to the transcluded content in clone. Then, we create the new header element with the appropriate level, append the content (in clone) to that, and then append that header element to the hx.
http://plnkr.co/edit/ED7NU8NmZ1g3G8efQNlu?p=preview

Default ngModel in angular directive not being set

I have this custom directive in angular that looks like this: (removed most of the code for brevity).
angular.module("SharedModule")
.directive('singleSelect', ['$ionicModal', singleSelect]);
function singleSelect($ionicModal) {
return {
restrict: 'E',
require: 'ngModel',
replace:true,
template: [
'<div class="item item-icon-right" ng-click="showItems($event)" >',
'{{text || headerText}}',
'<i class="icon ion-ios-arrow-right"></i>',
'</div>'
].join("")
,
scope: {
items: "=",
headerText: "#"
},
link: function (scope, element, attrs, ngModelController) {
if (ngModelController.$modelValue){ // i even tried $viewValue here
scope.selectedItemId = ngModelController.$modelValue.id;
scope.text = ngModelController.$modelValue.text;
}
scope.change = function (item) {
ngModelController.$setViewValue(item);
scope.text = ngModelController.$viewValue.text;
scope.close();
};
}
}
}
I set the default for the ng-model as:
<single-select ng-model='defaultValue' header-text='text when no default present'>
and setting the value for defaultValue to {id:"1",label:"foo"} in the scope.
I expect that my template shows a foo when rendering my directive template but it does not. Debugging shows that my ngModel values are set to NaN. I am sure i am missing something trivial here. What could it be?
Also, how could i display my ngModel's label value in the template without an intermediate scope property like the text i have used.
UDPATE: i have created a sample jsfiddle to explain the problem well.
I expect my div to display foo in the jsfiddle and not the default text.
if you replace you make you set your header text as follows foo will appear header-text={{defaultValue.text}} and remove ng-model, you can use angular's default templeting system
I've included a full JSfiddle: http://jsfiddle.net/0Lpy7gff/

Assign random ngModel to directive

I'm trying to assign a random string to ngModel. But I can't even seem to assign a regular string to it. In the code below, I'm trying to change the ngModel to "new", but in chrome, it's still showing me that the ngModel is "placeholder". What am I doing wrong?
app.directive("page", function(){
return {
restrict: 'E',
replace: true,
template: '<div ng-model="placeholder"></div>',
controller: function ($scope, $element) {
$scope.placeholder = "new";
}
}});
The plain div tag was just an example. What I actually have is a content editable div that I've bound to a textarea with a contenteditable directive. I made a button to allow me to add as many of these directives as I want, but when I add this directive, I'd like a new ng-model for each one, because that's what I'm using to save the content of each content editable div to a file.
This is the full example in case it might help someone else. I put the addPage directive to a button, which, when clicked, appends a new content editable div (which I'm calling a page). There is one more directive that I didn't include (contenteditable) because I got it from the bottom of the docs over here
app.directive("addPage", function($compile){
return function(scope, element, attrs){
element.bind("click", function(){ angular.element(document.getElementById('container')).append($compile('<page></page>')(scope));
});
};
});
app.directive("page", function(){
return {
restrict: 'E',
replace: true,
// template: '<div class="page" contenteditable strip-br="true" ng-model="chapter"></div>',
template: function (elem, attr) {
var test="chapter.two"; //in reality, I will generate a random string to keep these divs unique
return '<div class="page" contenteditable strip-br="true" ng-model=' + test +'></div>'
}
}});
In my controller, I have this object that is used to store all the ng-model content
$scope.chapter = {};
I think you are approaching this a bit backwards. Starting with the model, you'd need an array to keep the values from all of the inputs / contenteditables.
.controller("MainCtrl", function($scope){
$scope.data = [{v: ""}]; // first element
$scope.addContentEditable = function(){
$scope.data.push({v: ""});
};
})
Then, you can bind to each element of that array easily, and add elements at will:
<button ng-click="addContentEditable()">Add</button>
<div ng-repeat="item in data" ng-model="item.v" contenteditable></div>
I'm not sure exactly how the page directive needs to be used here, but one way or another, the approach is the same as above.
If you just want to pass a string in you could use attributes and template(fn)
HTML
<div page="new">
Directive
app.directive("page", function () {
return {
restrict: 'E',
replace: true,
template: function (elem, attr) {
return '<div ng-model="' + attr.page + '"></div>';
}
}
});

mouseover event Angular JS access attributes

I have the following directive
courseApp.directive("courseoverview", function() {
function link(scope, element, attrs) {
scope.switched = false;
//hover handler
scope.hoverItem = function(hovered){
if (hovered) {
//element.addClass('hover');
$('#course-'+ scope.$index +' figure').addClass('tint');
//console.log(scope.$index);
}
else
//element.removeClass('hover');
$('#course-'+ scope.$index +' figure').removeClass('tint');
};
}
return {
restrict : 'A',
replace: true,
transclude: true,
templateUrl: "views/course-overview.html",
link: link
}});
The directive is called with the following code
<li data-ng-repeat="item in social" class="social-{{item.name}}"
ng-mouseover="hoverItem(true);"
ng-mouseout="hoverItem(false);"
current-social="{{item.name}}">
The hover function works great but i need access to this attribute in the directive, well i need the value of it.
Any ideas on how to achieve this would be great.
First, your directive is named 'courseoverview' but I don't see that attribute anywhere in the markup you provided.
To address your question, you say I need access to this attribute in the directive. But I think you have the attributes in the link function - see the attrs parameter. Those are the attributes on the element that fired your directive.
function link(scope, element, attrs) { ... }
See this answer for more.

Change HTML with angularJS syntax using a directive

I'm trying to learn AngularJS a bit and I want to do the following:
Create a table which has sortable columns and have an arrow image that describes the sorting direction.
What I tried to do is creating a directive called sort which takes the sorting column and changes the sortByColumn variable. This works fine. The only problem is when I try to change the class of the image.
At first I tried using the template to use like this:
link: function(scope, element, attrs)
{
...
},
template: '<span class="image" ng-class="{is-visible: someVar == attrs.sort}"></span>'
This doesn't work because the attrs variable is not defined so the first question would be... is there a way to access the element's attributes inside the template?
If not, what I tried to do next is manually set the html inside the link:
link: function(scope, element, attrs)
{
element.html('' + element.html() + '<span class="sort-image" ng-class="{visible: true}"></span>');
}
This doesn't work because it doesn't evaluate the ng-class.
How can I achieve such a thing?
myApp.directive('sort', function () {
return {
scope: {
sort: "#"
},
link: function (scope, element, attrs) {
...
},
template: '<span style="display:inline-block;" ng-transclude></span><span class="sort-image" ng-class="{visible: sort == (sortByColumn)}"></span>',
transclude: true
};
});
I figured out the answer. I can just use the isolate scope "#" to pass the attribute value.

Resources