pass $scope value of a constructor function to directive - angularjs

Here i want to pass $scope.myData of app.js to the directive mcsaForm and use the object attributes in myTemplate.html. My code is working properly except the approach which i mentioned above.
app.js
myApp.controller("myCont", function($scope){
.
some code
.
.
$scope.getTypeOfEvent = function(typeOfEvent, idOfEvent)
{
if(typeOfEvent == "MCQ")
{
if(idOfEvent)
{
var indexOfEvent =$scope.namesTwo.Events.indexOf("idOfEvent")+1;
var valueAtIndex = $scope.namesTwo.Events[indexOfEvent].id;
$scope.myData = $scope.namesTwo[valueAtIndex];
console.log($scope.myData); // output: Object {eventId: "001", TimeOfEvent: "2", EventType: "MCQ"}
}
//fetchJsonDir.gettingContData;
$scope.mCSSQ(typeOfEvent,idOfEvent);
}
}
});
myDirective.js
videoCourseApp.directive("mcsaForm",['fetchJsonDir', function(fetchJsonDir){
return{
restrict: "C",
templateUrl: "assets/template_blocks/Preview_forms/myTemplate.html",
scope: {
myData: "="
},
compile: function(scope, element, attrs)
{
$("#mcss_option_list").append("Hello");
},
controller: function($scope){
$scope.onSubmitHidePanel = function()
{
$(".mcsa_form").fadeOut("slow", function(){
$(this).remove();
});-
}
}
}
}]);
myTemplate.html
<div id=mcss_option_list>
</div>
<div>
001, 2, MCQ//print myData.eventId, myData.TimeOfEvent or whatever..
</div>

Use your directive like
<div class="mcsa-form" my-data="myData"></div>
You will get the value in your directive's myTemplate.html
<div id=mcss_option_list>
{{myData.TimeOfEvent}}
</div>

Related

angularjs how to access controller $scope variable in directive isolated scope

In angularjs I have been trying to access main controller $scope variable in my directive isolated scope.
My html code,
<body ng-controller="MainCtrl">
<div id="TestContainer" class="TestContainer" ng-init=Intialfunc()>
<collection collection='testdata'>{{testdata}}</collection>
</div>
</body>
My directive code,
var app = angular.module('plunker', []);
app.directive('collection', function () {
return {
restrict: "E",
replace: true,
scope: {collection: '='},
//controller: 'TreeController',
//bindToController: true,
template: "<ul><member ng-repeat='member in collection' member='member'></member></ul>"
}
})
app.directive('member', function ($compile) {
var linkerfunc = function(scope, element, attrs) {
var collectionSt = '<collection collection="member.children"></collection>';
$compile(collectionSt)(scope, function(cloned, scope) {
element.append(cloned);
});
}
return {
restrict: "E",
replace: true,
scope: {member: '=', ShowDetailsCtrlFunc : '&'},
template: "<li><span ng-click=ShowDetailsCtrlFunc()>{{member.NodeName}}</span></li>",
controller: 'MainCtrl',
//controllerAs: 'MainCtrl',
//bindToController: true,
link: linkerfunc
}
})
My controller code,
app.controller('MainCtrl', function ($scope) {
$scope.Intialfunc = function() {
$scope.testdata = []
var myjsondata = JSON.parse('{ "NodeName": "Parent", "children": [ { "NodeName": "mychild", "children": [ { "NodeName": "chld1", "children": [] } ] } ] }');
$scope.testdata.push(myjsondata);
console.log($scope.testdata) //This one is showing
}
$scope.ShowDetailsCtrlFunc = function(element,event) {
console.log("in function ShowDetailsCtrlFunc"); // coming to this fucntion on click.
console.log($scope.testdata) // but this one is not showing . shows undefined.
//event.stopImmediatePropagation();
};
});
it is coming to the function but not showing the controller $scope. I have created a plunker ,
plunker
Please help me. I have been struggling for many days.
You need to add a function expression to both of your directives' isolate scopes in order to properly call a function in your parent scope. Taking your original code, it should look something like this:
var app = angular.module('plunker', []);
app.directive('collection', function () {
return {
restrict: "E",
//replace: true, <- this is deprecated and should no longer be used
scope: {
collection: '=',
onMemberClick: '&'
},
template: "<ul><member ng-repeat='member in collection' member='member' on-click='onMemberClick()'></member></ul>"
}
})
app.directive('member', function ($compile) {
return {
restrict: "E",
//replace: true, <- this is deprecated and should no longer be used
scope: {
member: '=',
onClick : '&'
},
template: "<li><span ng-click='onClick()'>{{member.NodeName}}</span></li>"
}
});
And you original html should look something like this:
<body ng-controller="MainCtrl">
<div id="TestContainer" class="TestContainer" ng-init=Intialfunc()>
<collection collection='testdata' on-member-click='ShowDetailsCtrlFunc ()'>{{testdata}}</collection>
</div>
</body>
Argument binding
If you would like to actually know which member was clicked, you'll need to bind arguments to your function calls.
var app = angular.module('plunker', []);
app.directive('collection', function () {
return {
restrict: "E",
scope: {
collection: '=',
onMemberClick: '&'
},
template: "<ul><member ng-repeat='member in collection' member='member' on-click='onMemberClick({member: member})'></member></ul>"
}
})
app.directive('member', function ($compile) {
return {
restrict: "E",
scope: {
member: '=',
onClick : '&'
},
template: "<li><span ng-click='onClick({member: member})'>{{member.NodeName}}</span></li>"
}
});
Html:
<body ng-controller="MainCtrl">
<div id="TestContainer" class="TestContainer" ng-init=Intialfunc()>
<collection collection='testdata' on-member-click='ShowDetailsCtrlFunc (member)'>{{testdata}}</collection>
</div>
</body>
MainCtrl:
app.controller('MainCtrl', function ($scope) {
$scope.Intialfunc = function() {
$scope.testdata = []
var myjsondata = JSON.parse('{ "NodeName": "Parent", "children": [ { "NodeName": "mychild", "children": [ { "NodeName": "chld1", "children": [] } ] } ] }');
$scope.testdata.push(myjsondata);
console.log($scope.testdata) //This one is showing
}
$scope.ShowDetailsCtrlFunc = function(member) {
console.log("In show details function");
console.log(member);
};
});
plunker
Lets Begin with the query you have. You want to call a function from link inside the directive even when the scope is isolated. It's simple you want to access parent scope.
Here's the code you can use to access parent scope.
scope.$parent.yourFun();
//or you can do this by the code give below.
//Inside Directive Use this.
scope:{
fun:"&"
},
//now you can call this function inside link
link:function(scope, element,attr){
scope.fun();
}
In your app.directive, just put scope : false.
Your directive will use the same scope as his parent scope.

How to call function of directive from controller

My directive code is:
(function() {
angular.module('app')
.directive('dynamicImage', dynamicImage);
function dynamicImage($timeout) {
return {
restrict: 'A',
scope: { dynamic:'&dynamicImage' },
link: function (scope, elem) {
scope.dynamic = function(){
//code here
}
}
};
}
})();
My Controller code is :
In controller How can I call??
function theMethodToBeCalled() {
$scope.dynamic();
}
My HTML:
<div class="col-xs-12" dynamic-image="theMethodToBeCalled">
<div class="meet_details_status_img" data-ng-repeat="user in meet.user" data-ng-if="user.extra.invitationStatus === 'pending'">
<img class="img-circle my-meets-status-img" ng-src="{{ user.displayPicture ? (imageURL + user.id) : 'assets/images/user_thumb.jpg' }}"
/>
</div>
</div>
Please Help me.
Thanks
You can expose an object from controller to directive and can define a method inside that object in the directive. Since you've access to the object which is exposed in directive so you can call any method defined in that directive.
Example -
(function() {
angular.module('app')
.directive('dynamicImage', dynamicImage);
function dynamicImage($timeout) {
return {
restrict: 'A',
scope: { dynamic:'&dynamicImage',methodList:'=' },
link: function (scope, elem) {
scope.methodList.dynamic = function(){
//code here
}
}
};
}
})();
In controller -
function CtrlFun($scope){
$scope.methodList = {};
$scope.callDirectiveMethod = function(){
$scope.methodList.dynamic();
}
}
HTML
<div dynamic-image method-list="methodList"> </div>

Calling a method within a controller that's within a custom directive

Been trying to figure this out for too long now. Maybe someone can shed some light:
Am experimenting with custom directives and as an exercise I'm trying to create a method within the custom directive's controller that can be called from a simple button within the view. But the method isn't being called, even though I can see the method (using console) as a property within isolated scope object. Any ideas please?
HTML:
<my-dir>
<p>My dir content</p>
<p><button ng-click="hideMe()">Hide element with isolated scope</button></p>
</my-dir>
JS:
var app = angular.module('myApp', []);
app.directive('myDir', function() {
return {
restrict: 'EA',
scope: {},
controller: ['$scope', function ($scope) {
$scope.hideMe = function(){
console.log('hideMe called');
};
}]
};
})
You have to declare your template inside the directive using template: property or inside an external .html file using templateUrl:"path/to/template.html"
Example using template :
var app = angular.module('myApp', []);
app.directive('myDir', function() {
return {
restrict: 'EA',
scope: {},
template : '<p>My dir content</p><p><button ng-click="hideMe()">Hide me</button></p>',
controller: ['$scope', function ($scope) {
$scope.hideMe = function(){
console.log('hideMe called');
};
}]
};
})
Example using templateUrl :
var app = angular.module('myApp', []);
app.directive('myDir', function() {
return {
restrict: 'EA',
scope: {},
templateUrl : 'my-dir.tpls.html',
controller: ['$scope', function ($scope) {
$scope.hideMe = function(){
console.log('hideMe called');
};
}]
};
})
Template : my-dir.tpls.html
<p>My dir content</p>
<p><button ng-click="hideMe()">Hide me</button></p>
HTML:
<my-dir></my-dir>
You can try this,
Directive:
app.directive('myDir', function() {
return {
restrict: 'EA',
scope: {},
link: function($scope, element, attrs) {
$scope.hideMe = function() {
alert('hideMe called');
}
}
}
});
HTML:
<div ng-controller="MyCtrl">
<my-dir>
<p>My dir content</p>
<p>
<button ng-click="hideMe()">Hide element with isolated scope</button>
</p>
</my-dir>
</div>
DEMO

AngularJs, when directive compile new attributes, the events are not triggered if there is a scope

I'm a bit stuck on an directive which add attributes and recompile the element.
If I had a scope on the directive ng-change is not triggered anymore (without it it works). I based my test on this answer
The HTML
<div ng-app="myApp">
<div ng-controller='testController'>
<div ng-repeat="field in fields">
<input type="text" ng-model="ngModel[field.fieldName]" property="{{formParams.getProperties(field.fieldName)}}" update-attr ng-change="test()" />
</div>
</div>
</div>
The directive:
angular.module('myApp', [])
.controller('testController', function ($scope) {
$scope.properties = {
"something": {
"style": "float:left;"
},
"something2": {
"style": "float:right;"
}
};
$scope.ngModel = {};
$scope.fields = [{
fieldName: 'something'
}, {
fieldName: 'something2'
}];
$scope.test = function () {
alert('i dont get triggered');
};
$scope.formParams = {
getProperties: function (fieldName) {
return $scope.properties[fieldName];
}
};
})
.directive('updateAttr', function ($compile) {
return {
restrict: 'A',
replace: true,
terminate: true,
scope: {
ngModel : '='
},
link: function (scope, elem, attrs) {
if (angular.isDefined(attrs['property']) && attrs['property'].lenght != 0) {
var json = JSON.parse(attrs['property']);
angular.forEach(json, function (value, key) {
elem.attr(key, value);
});
elem.removeAttr('property');
var $e = $compile(elem[0].outerHTML)(scope);
elem.replaceWith($e);
}
}
};
});
Here a fork of the fiddle to test with a scope on the directive: fiddle
Do you have any suggestion ?
I found why ng-change was not trigger so I share the answer:
When we add scope attribute on the directive, a new scope is created. So we have to use $scope.$parent for the compilation. I have updated the fiddle with the correction.

angularJS how to $eval the function with parameter

I am trying to implement the directive, in the directive, I want to $eval the values which contains the function name and parameter value:
Html page:
<select mydirective="action('pValue')">
AngularJS directive code:
app.directive('mydirective', function ($timeout) {
return {
restrict: 'A',
link: function ($scope, element, attr) {
$timeout(function () {
$scope.$eval(attr.mydirective);
});
}
}
What I am expected is it will invoke the action function define in scope and pass the pValue as function parameter. How can I make it work please?
What you want happen automatically, the function will invoke with the value, this is the purpose of eval:
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
$scope.action = function(val) {
alert(val);
}
});
app.directive('mydirective', function($timeout) {
return {
restrict: 'A',
link: function($scope, element, attr) {
$timeout(function() {
$scope.$eval(attr.mydirective);
});
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.21/angular.min.js"></script>
<div ng-app="plunker" ng-controller="MainCtrl">
<select mydirective="action('pValue')"></select>
</div>
For those whom looking for a way to pass $event info to custom directive method see example below:
TEMPLATE:
<div on-touch-end="onTouchEnd( 'some data' )">
TOUCH ME!
</div>
CONTROLLER:
$scope.onTouchEnd = function( data ) {
console.log("onTouchEnd event with data", data, event );
};
DIRECTIVE:
.directive('onTouchEnd', function() {
return {
restrict : 'A',
link : function( $scope, $element, $attr ) {
$element.on('touchend', function( event ) {
$scope.$apply(function() {
$scope.$eval( $attr.onTouchEnd );
});
});
}
}
})

Resources