Thanks in advance,Actually I want to call a function in controller from app.Directive, Please anyone let me know How I can call?Also I passing parameter to that function?I'm new in angular and here is all code.
var app = angular.module('quizApp', []);
app.controller("SaveCtrl", function (scope) {
$scope.Save = function (score) {
$scope.TestDetailsViewModel = {};
$scope.TestDetailsViewModel.CorrectAnswer = $scope.score;
$http({
method: "post",
url: "/Home/ResultSave",
datatype: "json",
data: JSON.stringify($scope.TestDetailsViewModel)
}).then(function (response) {
alert(response.data);
})
};})
app.directive('quiz', function (quizFactory) {
return {
restrict: 'AE',
scope: {},
templateUrl: '/Home/Dashboard',
link: function (scope, elem, attrs) {
scope.getQuestion = function () {
var q = quizFactory.getQuestion(scope.id);
if (q) {
scope.question = q.question;
scope.options = q.options;
scope.answer = q.answer;
scope.answerMode = true;
} else {
scope.quizOver = true;
//Calling function save(); in Controller
//scope.Save(scope.score);
}
};
}
}});
In the case of an isolated scope, the directive scope is completely unaware of its parent’s scope.
To call a function of a controller you have to bind that function to the scope of directive and then call scope functions from inside the directive.
For example:
app.controller('MainCtrl', function($scope) {
$scope.commonFunc = function(passed){
$scope.name = passed;
};
});
app.directive('demodirective', function(){
return {
scope: {
commonFunc: '&'
},
link: function(scope){
scope.commonFunc({passed:"world"});
}
};
});
HTML
<body ng-controller="MainCtrl">
<demodirective common-func="commonFunc(passed)">
</demodirective>
Hello {{name}}
</body>
For Reference - https://plnkr.co/edit/fMIsQ87jgdx49QSnWq4o?p=preview
Related
My ajax fires after the complete directive executes. Is there any work around for this so that I can have my grid configuration loads before coming to the grid directive
gridApp.directive('grid', function () {
return {
restrict: "EA",
scope: {
gridName: "#"
},
template: '<h1>kendoDirective</h1><br/><div kendo-grid={{gridName}} options="gridOptions"></div>',
controller: function ($scope, $element, $attrs, widgetUtils) {
var gridConfig = widgetUtils.GetGridOption().then(onLoad);
var onLoad = function (data) {
$scope.gridOptions = data;
}
console.log('DirectiveScope: ' + $scope.gridOptions);
},
link: function ($scope, $element, $attrs) {
}
};
});
gridApp.service('widgetUtils', function ($http) {
var getGridOption = function () {
return $http.get('/Base/LoadGridConfiguration').then(function (response) {
return response.data;
});
}
return {
GetGridOption: getGridOption
};
});
You can handle it with ng-if in template. I created $scope.isReady and change it state after options loaded.
gridApp.directive('grid', function () {
return {
restrict: "EA",
scope: {
gridName: "#"
},
template: '<h1>kendoDirective</h1><br/><div data-ng-if="isReady" kendo-grid={{gridName}} options="gridOptions"></div>',
controller: function ($scope, $element, $attrs, widgetUtils) {
var gridConfig = widgetUtils.GetGridOption().then(onLoad);
$scope.isReady = false;
var onLoad = function (data) {
$scope.gridOptions = data;
$scope.isReady = true; // here we ready to init kendo component
$scope.$apply();
}
console.log('DirectiveScope: ' + $scope.gridOptions);
},
link: function ($scope, $element, $attrs) {
}
};
});
I have a angular element on the page which needs to communicate with the rest of the non angular page elements.
I am creating directive elements on the fly, and appending it to its target div. I am trying to pass that created directive an object (ajax object), which contains just attributes.
The issue is that I can't figure out how to pass just this ajax object to the directive, as $compile requires a scope. When the http finishes, and because i have to use = in the directive, the directives are being over-ridden.
Please see my plunk: https://plnkr.co/edit/brTWgUWTotI44tECZXlQ ( sorry about the images ). Click the <button> to trigger the directive.
(function() {
'use strict';
var CHANNEL = 'podOverlay';
angular.module('CavernUI', [])
.controller('CavernCtrl', function($scope,getItemService) {
$scope.model = {};
var _pods = $scope.model.pods = {};
function getData(selector) {
$(selector).each(function(i, pod) {
_pods[+pod.dataset.item] = {
$: $(pod)
};
});
Object.keys($scope.model.pods).map(function(key) {
getItemService.getItem(key).success(function(response) {
_pods[key] = angular.extend(_pods[key], response);
$scope.$broadcast(CHANNEL, _pods[key], $scope);
});
})
}
$scope.runPodCheck = function(selector) {
getData(selector);
}
})
.directive('podchecker', function($compile) {
var createOverlay = function(e,data,scope){
scope.data = data;
// can i just pass data rather than scope.data?
// If I pass the scope, then when another $broadcast happens
// the scope updates, wiping out the last scope change.
// Scope here really needs to be a static object that's
// created purely for the hand off. But I don't know if
// that can be done.
angular.element(data.$[0]).empty().append($compile('<overlay data="data"></overlay>')(scope));
}
return {
restrict: 'E',
scope: {
check: '&',
},
templateUrl: 'tpl.html',
link: function(scope,elm,attr){
scope.$on(CHANNEL,createOverlay);
}
};
})
.directive('overlay', function() {
return {
restrict: 'E',
scope: {
o: '=data' // here is the problem.
},
template: '<div class="overlay"><img ng-src="{{o.images.IT[0]}}"/></div>',
link: function(scope, elm, attr) {
}
}
})
.service('getItemService', ['$http', function($http) {
this.getItem = function(itemId) {
return $http({
method: 'GET',
url: 'https://www.aussiebum.com/ajaxproc/item',
params: {
id: itemId,
ajxop: 1
},
});
};
}]);
}());
Edits:
Expected ouput:
I'm not sure this is the best approach, but one way might be to manually create a new scope for each of the overlays.
So changed this:
var createOverlay = function(e,data,scope){
scope.data = data;
angular.element(data.$[0]).empty().append($compile('<overlay data="data"></overlay>')(scope));
}
to this:
var createOverlay = function(e,data,scope){
var overlayScope = scope.$new(false); // use true here for isolate scope, false to inherit from parent
overlayScope.data = data;
angular.element(data.$[0]).empty().append($compile('<overlay data="data"></overlay>')(overlayScope));
}
Updated Plnkr: https://plnkr.co/edit/wBQ1cqVKfSqwqf04SnPP
More info about $new()
Cheers!
I cannot get the parent function call from the isolated scope..The purpose of this code is to create a widget directive which can be used multiple times on the same page... I tried some other option, but doesn't work either. It works using the parent scope.
What am I missing here.
var app = angular.module("winApp", []);
app.controller("winCtrl", function($scope, dataFactory) {
$scope.getData = function() {
dataFactory.get('accounts.json').then(
function(data) {
$scope.items = data;
});
};
});
app.directive("windowSmall", function() {
return {
restrict : 'EA',
replace : 'true',
scope : {
type : '&'
},
transclude: 'true',
templateUrl : 'windowtemplate.html',
link : function(scope, element, attrs) {
element.bind("load", function(){
console.log(attrs.type);
if (angular.equals(attrs.type, 'getData()')) {
scope.active = 'accounts';
console.log(attrs.type);
// scope.getData();
scope.$apply(function() {
scope.$eval(attrs.type);
});
}
});
}
};
});
app.factory('dataFactory', function($http) {
return {
get : function(url) {
return $http.get(url).then(function(resp) {
return resp.data;
});
}
};
});
HTML:
<div ng-app="winApp" ng-controller="winCtrl">
<window-small type = "getData()"> </window-small>
<br> <br>
<!--
<window-small type = "bulletin"> </window-small> -->
You can also use $rootScope for a full proof solution. Due to the fact that an application can have multiple parents but only one $rootScope.
https://docs.angularjs.org/api/ng/service/$rootScope
Replace your link function with :
link : function(scope, element, attrs) {
element.bind("load", function(){
console.log(attrs.type);
if (angular.equals(attrs.type, 'getData()')) {
scope.active = 'accounts';
console.log(attrs.type);
scope.type();
}
});
}
Fiddle : http://jsfiddle.net/X7Fjm/3/
I'm trying to render code in the link function after the controller resolves the http call but the link function is called before that. How can I call link after $scope.menuHtml has been set?
HTML:
<div id="testD" nav-menu-output="parseMenuJsonAndOutPutMenu()"></div>
DIRECTIVE:
return {
restrict: 'A',
controller: ['$scope', '$q','$http', function ($scope, $q,$http) {
$http.get('ajax/menu' ).then(function (data) {
$scope.menuHtml = generateHtmlMenu(data);
});
}],
link: function(scope, element, attr) {
var templateString = scope.menuHtml;
var compiledTemplate = $compile(templateString)(scope);
compiledTemplate.appendTo("#testD");
}
}
I would suggest using scope.$watch() and rerunning your compiled template code on that. This way you can make as many requests to the menu endpoint as you want and your template will be recompiled.
Here's more information about watch:
http://docs.angularjs.org/api/ng/type/$rootScope.Scope#$watch
Here's an updated version which should work properly:
return {
restrict: 'A',
controller: ['$scope', '$q','$http', function ($scope, $q,$http) {
$http.get('ajax/menu' ).then(function (data) {
$scope.menuHtml = generateHtmlMenu(data);
});
}],
link: function(scope, element, attr) {
scope.$watch('menuHtml', function() {
var templateString = scope.menuHtml;
var compiledTemplate = $compile(templateString)(scope);
compiledTemplate.appendTo("#testD");
});
}
}
You can do it by using async: false
Please Try this code instead of your code,
return {
restrict: 'A',
controller: ['$scope', '$q','$http', function ($scope, $q,$http) {
$http({
method: 'GET',
url: 'ajax/menu',
async: false
}).success(function (data) {
$scope.menuHtml = generateHtmlMenu(data);
})}],
link: function(scope, element, attr) {
var templateString = scope.menuHtml;
var compiledTemplate = $compile(templateString)(scope);
compiledTemplate.appendTo("#testD");
}
}
I have some issues with directive scopes...
wall.directive('onPaste', function() {
return{
restrict: 'A',
scope :true,
controller: function($scope, $http) {
$scope.getUrlInfos = function() {
$http({
method: 'POST',
data: {
firstPost: $scope.firstPost,
lastPost: $scope.lastPost
},
url: '/wall/json/parseUrl.json'
}).success(function(data){
$scope.firstPost = 99;
$scope.parseUrl = data; // response data
console.log($scope);
});
}
},
link: function (scope, element, attrs, parentCtrl) {
element.bind("paste", function(event) {
var element = this;
setTimeout(function () {
var text = $(element).val();
urls = findUrls(text);
scope.$apply(function(){
scope.firstPost = 10;
scope.getUrlInfos();
})
}, 100);
});
}
};
});
When I console.log($scope); the variable has all the scope... but as I understand it is a copy of the root scope. Any change to this scope doesn't appear on the screen. How can I return this scope to the root scope?
Assume that you have a defined root scope,
wall.run(function($rootScope){
$rootScope.firstPost = 1;
//.....
});
In AngularJS, $scopes prototypically inherit from their parent scope, all the way up to $rootScope. In JavaScript, primitive types are overwritten when a child changes them. So when you set $scope.firstPost in one of your controllers, the property on $rootScope was never touched, but rather a new visible property was added to the current scope.
So you need to pass the rootScope to directive controller,then change from there.
wall.directive('onPaste', function() {
return{
restrict: 'A',
scope :true,
controller: function($scope, $rootScope, $http) {
$scope.getUrlInfos = function() {
$http({
method: 'POST',
data: {
firstPost: $rootScope.firstPost,
lastPost: $rootScope.lastPost
},
url: '/wall/json/parseUrl.json'
}).success(function(data){
$rootScope.firstPost = 99;
$rootScope.parseUrl = data; // response data
console.log($rootScope);
});
}
},
link: function (scope, element, attrs, parentCtrl) {
element.bind("paste", function(event) {
var element = this;
setTimeout(function () {
var text = $(element).val();
urls = findUrls(text);
scope.$apply(function(){
scope.firstPost = 10;
scope.getUrlInfos();
})
}, 100);
});
}
};
});