Angular directive that uses dynamic value - javascript

I am trying to write a simple json pretty-printer directive in angular.js. I have:
(function(_name) {
function prettyJson() {
return {
restrict: 'E',
template: '',
link: function($scope, $element, $attr) {
console.log($element.text());
//$element.html(angular.toJson(angular.fromJson($element.text()), true));
}
};
}
angular
.module('ourApp')
.directive(_name, prettyJson);
})('prettyJson');
In my view I am doing:
<pretty-json>{{ auth.get() }}</pretty-json>
The problem is that console.log($element.text()) comes back as {{ auth.get() }} not the angular compiled result of the function call auth.get().
How do I make the directive use the result of the function call auth.get()?

I would swap to using an attribute directive and use the $attr.$observe() function to set up a $watch-like mechanism that will call a listener function every time the interpolated value of the attribute changes.
The directive code:
(function(_name) {
function _directive() {
return {
restrict: 'A',
link: function($scope, $element, $attr) {
$attr.$observe(_name, function (json) {
$element.text(angular.toJson(angular.fromJson(json), true));
});
}
};
}
angular
.module('ourApp')
.directive(_name, _directive);
})('prettyJson');
Usage in markup:
<pre pretty-json="{{ auth.get() }}"></pre>
See my Plunkr example.

You could just pass the content you want to format in as a parameter to your directive. e.g.:
JS
(function(_name) {
function prettyJson() {
return {
restrict: 'E',
scope: {
prettyJson: '='
},
template: '<pre>{{prettyJson | json}}</pre>',
};
}
angular
.module('ourApp')
.directive(_name, prettyJson);
})('prettyJson');
HTML
<pretty-json="auth.get()"></pretty-json>

Related

How to read a html data value in AngularJs directive

I am very new to Angular. I am trying to read/pass some data to my angular directive from the template.
<div class="col-md-6" approver-picker="partner.approverPlan.data" data-pickerType="PLAN"></div>
I have this in my angular template and I have this in different places. So I want to know in my Angular code, which picker is being clicked.
I am thinking to read the data-pickerType value in my directive.(I am able to read this in jQuery but do not know how to in Angular)
This is my directive code.
Partner.Editor.App.directive('approverPicker', [
'$compile', function ($compile) {
return {
scope: {
"approvers": "=approverPicker"
},
templateUrl: '/template/assets/directive/ApproverPicker.html',
restrict: 'EA',
link: function ($scope, element) {
...........
}
};
}
]);
How can I read the data-pickerType value in the directive or is there a better way of doing this?
The data attributes can be accessed in Angular directive by passing attrs variable in the link function.
Partner.Editor.App.directive('approverPicker', [
'$compile', function ($compile) {
return {
scope: {
"approvers": "=approverPicker"
},
templateUrl: '/template/assets/directive/ApproverPicker.html',
restrict: 'EA',
link: function ($scope, element, attrs) { //passing attrs variable to the function
//accessing the data values
console.log(attrs.pickertype);
//you can access any html attribute value for the element
console.log(attrs.class);
}
};
}
]);

Attribute undefined in custom directive in angularjs

I am creating a custom directive in angularjs, but for some attributes i am receiving undefined value.
function processinfo(ProcessInfoService, $timeout) {
console.log("processInfo directive");
return {
restrict: 'E',
scope: {
start: '=',
end: '=',
uuid: '='
},
templateUrl: 'k2-modules/js/directives/templates/processInfoTemplate.html',
controller: function($scope) {
var self = this;
console.log($scope.uuid); // undefined
console.log($scope.end); // 164982555555
console.log($scope.start); // 0
self.processData = ProcessInfoService.getInfo($scope.start, $scope.end);
}
}
}
<processinfo start="0" end="164982555555" uuid="a57cf6f8"></processinfo>
For uuid I am getting undefined but for end and start values everything is working fine. I don't know why this is happening since syntax is same for all three. Any help will be appreciated
Your mixing directive syntax with component/controller syntax, in directives $scope is called scope (no dollar). Here's the correct syntax to build a angularjs directive:
angular.module('app').directive('myDirective', MyDirective);
MyDirective.$inject = ['$timeout'];
function MyDirective($timeout) {
return {
scope: {
'propBinding1': '<',
'propBinding2': '&'
},
replace: true,
restrict: 'EA',
templateUrl: 'path to html',
link: function link(scope, element, attrs) {
//... do stuff here ...
}
};
}

how create dynamic template with directive attribute value

I create a directive, and want to use dynamic template with attribute wm.data.typeName.
wm.data.typeName = "<span>html code</span>"
<fill-choose model-input="wm.data.modelInput" text="wm.data.typeName"></fill-choose>
and directive fillChoose is
(function() {
'use strict';
angular
.module('learn')
.directive('fillChoose', fillChoose);
/** #ngInject */
function fillChoose($showdown) {
var directive = {
restrict: 'AE',
template: function(elem, attr) {
//return $showdown.makeHtml(fill.modelInput);
return '<div>'+ attr.modelInput +'</div>';
},
scope: {
modelInput: '=',
text: '='
},
controller: FillChooseController,
controllerAs: 'fill',
bindToController: true
};
return directive;
/** #ngInject */
function FillChooseController($scope) {
var vm = this;
}
}
})();
But in this way, template will be <div>wm.data.modelInput</div>.
How to make the template be <div><span>html code</span></div> ?
link: function(scope, elem, attr) {
//return $showdown.makeHtml(fill.modelInput);
elem.html($compile('<div>{{fill.modelInput}}</div>')(scope));
}
Now for this very case a simple
template:'<div>{{fill.modelInput}}</div>';
Would work, but i gave the $compile thing because you may gave only a simplified version of what you're really trying to do.
you have to print it
<fill-choose model-input="{{ wm.data.modelInput }}" text="wm.data.typeName"></fill-choose>
but this will work once, because template function will call once, when directive is initialized (when angular calles compile to compile template), that's why you need to pass it through directive's scope

Sharing Data between two Directives in AngularJS

I have the following code:
<div id='parent'>
<div id='child1'>
<my-select></my-select>
</div>
<div id='child2'>
<my-input></my-input>
</div>
</div>
I also have two directives which get some data from the data factory. I need the two directives to talk to each other such that when a value in select box is changed the input in changes accordingly.
Here's my two directives:
.directive("mySelect", function ($compile) {
return {
restrict: 'E',
scope:'=',
template: " <select id='mapselectdropdown'>\
<option value=map1>map1</option> \
<option value=map2>map2</option> \
</select>'",
link: function (scope, element, attrs) {
scope.selectValue = //dont konw how to get the value of the select
}
};
})
.directive("myInput", function($compile) {
return {
restrict: 'E',
controller: ['$scope', 'dataService', function ($scope, dataService) {
dataService.getLocalData().then(function (data) {
$scope.masterData = data.input;
});
}],
template: "<input id='someInput'></input>",
link: function (scope, element, attrs) {
//here I need to get the select value and assign it to the input
}
};
})
This would essentially do the onchange() function that you can add on selects. any ideas?
You could use $rootScope to broadcast a message that the other controller listens for:
// Broadcast with
$rootScope.$broadcast('inputChange', 'new value');
// Subscribe with
$rootScope.$on('inputChange', function(newValue) { /* do something */ });
Read Angular docs here
Maybe transclude the directives to get access to properties of outer scope where you define the shared variable ?
What does this transclude option do, exactly? transclude makes the contents of a directive with this option have access to the scope outside of the directive rather than inside.
-> https://docs.angularjs.org/guide/directive
After much research this is what worked...
I added the following:
.directive('onChange', function() {
return {
restrict: 'A',
scope:{'onChange':'=' },
link: function(scope, elm, attrs) {
scope.$watch('onChange', function(nVal) { elm.val(nVal); });
elm.bind('blur', function() {
var currentValue = elm.val();
if( scope.onChange !== currentValue ) {
scope.$apply(function() {
scope.onChange = currentValue;
});
}
});
}
};
})
Then on the element's link function I added:
link: function (scope, elm, attrs) {
scope.$watch('onChange', function (nVal) {
elm.val(nVal);
});
}
Last added the attribute that the values would get set to in the scope:
<select name="map-select2" on-change="mapId" >

AngularJS: Watch a property of the parent scope

I'm quite new to AngularJS and I'm trying to understand a few things.
First of all, I have my controller of which I will place a snippet here:
var OfficeUIRibbon = angular.module('OfficeUIRibbon');
// Defines the OfficeUIRibbon controller for the application.
OfficeUIRibbon.controller('OfficeUIRibbon', ['$scope', '$http', function($scope, $http) {
var ribbon = this;
ribbon.setApplicationMenuAsActive = function() {
ribbon.applicationMenuActive = true;
}
}
Then I have a directive:
var OfficeUIRibbon = angular.module('OfficeUIRibbon');
OfficeUIRibbon.directive('ribbonApplicationMenu', function() {
return {
restrict: 'E',
replace: false,
scope: {
data: '#'
},
templateUrl: function(element, attributes) {
return attributes.templateurl;
}
}
});
The directive is called like this:
<ribbon-application-menu templateUrl="/OfficeUI.Beta/Resources/Templates/ApplicationMenu.html" data="/OfficeUI.Beta/Resources/JSon/Ribbon/ribbon.json"></ribbon-application-menu>
This does all work and in my template for the directive, the following is placed:
<div id="application" id="applicationMenuHolder" ng-controller="OfficeUIRibbon as OfficeUIRibbon" ng-show="OfficeUIRibbon.applicationMenuActive"...
From inside another element, when I execute a click a function on my controller is executed:
ng-click="OfficeUIRibbon.setApplicationMenuAsActive()"
Here's the directive from the other element:
OfficeUIRibbon.directive('ribbon', function() {
return {
restrict: 'E',
replace: false,
scope: {
data: '#'
},
templateUrl: function(element, attributes) {
return attributes.templateurl;
}
}
});
This function does change the property "applicationMenuActive" on the ribbon itself, which should make the item in the directive template show up.
However, this is not working. I'm guessing I need to watch this property so the view get's updated accordingly.
Anyone has an idea on how this could be done?

Categories

Resources