Angular - pass object from directive to parent scope on click - angularjs

I'm using an angular directive to generate a reusable template and show some data in it. The directive also has an ng-click that should take an object and pass it to the parent controller. I'm kind of stuck, not really sure how to pass that data from the directive controller to the scope of the parent controller. I read here but the circumstances are a bit different.
The js code of the directive:
angular.module("app")
.directive('userData', function() {
return {
restrict: "E",
templateUrl: "directives/userData/userData.html",
scope: {
userObj: "="
},
controller: function($scope){
},
link: function(scope, elements, attrs, controller){
}
}
});
And this is the directive html:
<div class="style" ng-click="displayFullDetails(userObj)">{{userObj.first_name}}</div>
Parent controller:
angular.module("app").controller("parentCtrl", ['$scope', function ($scope) {
angular.element(document).ready(function () {
getDataService.getJsonData().then(function (data) {
$scope.users = data.data;
})
});
}]);

Related

How to watch controller asynchronous data in angular directive

I define a directive in angular 1.4,which receives a scope parameter “b”:
(function() {
'use strict';
angular
.module('m')
.directive('mydirective', mydirective);
/** #ngInject */
function mydirective() {
var directive = {
restrict: 'E',
templateUrl: 'app/components/mydirective/mydirective.html',
scope: {
b: '='
},
controller: MydirectiveController,
controllerAs: 'vm',
bindToController: true
};
return directive;
/** #ngInject */
function MydirectiveController($scope, $state) {
var vm = this;
//here How to watch the parameter b to refresh the directive html result?
}
in html page:
<mydirective b="ctrl.b"></myupl>
in the business controller, b is got from an angular resource
PayService.getBusinessNumber().then(function(results){
vm.b = {business_id: results.no};
});
in index.route.js which define the route and the business controller,
$stateProvider
.state('payShowInfo', {
url: '/payShowInfo',
templateUrl: 'app/pay_show_info.html',
controller: 'PayShowController',
controllerAs: 'ctrl'
});
my problem is , When the directive loaded, the parameter “b” is undefined,  How to watch controller asynchronous data in angular directive? and then use the new value of “b” to refresh the html page?
If you define the directive parameter as "=", you mean that you will have two way data binding. So if you change the value in the controller, you will have the change reflected in the view.
angular.module('nib', [])
.directive('mydirective', function ($timeout) {
return {
restrict: 'E',
scope: {
b: '='
},
link: function ($scope, element, attrs) {
},
template: '<div>Test: {{b}}</div>'
};
})
.controller('ctrl',function($scope){
$scope.click = function(){ // emulating asynchronous request
$scope.test = 'testing';
}
})
See in the plnkr below:
http://plnkr.co/3qs1NpU1aIhKzxyCMXjh?p=preview

How do I access ng-controller from directive?

I've written my own directive from which I want to call a method on the parent ng-controller. I've tried doing that by adding require:'ngController' in my directive. However the returned controller is just an empty object. I'm running 1.4.8.
<div ng-controller="myController">
<div my-directive></div>
</div>
app.directive('myDirective', function() {
return {
restrict: 'A',
scope: false,
require: '^ngController',
link: function (scope, $element, attrs, controller) {
//controller is empty object..
};
}
});
Update: My misstake was that I added a method to the controllers scope when I should add it directly to the controller instead.
app.controller('myController', function($scope) {
$scope.myMethod = function() {}; //Not callable from controller passed to directive
this.myMethod = function() {}; //IS callable from controller passed to directive
});
You can call the parent controller via scope if your directive doesn't have an isolated scope, and you don't need to require ngController.
angular.module('app', [])
.controller('controller', function($scope) {
$scope.greet = function() {
return 'hi'
};
})
.directive('testDirective', function() {
return {
restrict: 'E',
template: '<h1>{{ greet() }}</h1>'
};
});
Output:
hi
Plnkr: http://plnkr.co/edit/uGXC5i1GjphcZCPDytDG?p=preview
The function needs to be available in the directive's scope. So if your directive is in the scope of the controller it is:
scope.fn();

inherit Angular parent directive attribute with isolate scope

I'm trying to inherit an attribute from a parent custom directive with isolate scope. In the example below, I want to be able to access the api attribute on myParent from the myChild controller or link function. My end goal is to inject an instance of the api that can be accessed by the children and from the view controller.
<my-parent api="parentInstance1">
<my-child ng-repeat="field in ::data"
ng-attr-src="{{field.src||undefined}}"
</my-child>
</my-parent>
<my-parent api="parentInstance2">
<my-child ng-repeat="field in ::data"
ng-attr-src="{{field.src||undefined}}"
</my-child>
</my-parent>
A simplified version of both directives looks like this
app.directive('myParent', function () {
return {
transclude: true,
restrict: "E",
scope: {
api: '=?'
},
template: '...',
controller: function ($scope, $attrs ) {
// foo is injected from a factory instance
function foo ( ) {
}
$scope.api = {
foo: foo
}
},
link: function ($scope, $element, $attr) {
}
}
});
app.directive('myChild', function () {
return {
require: "^myParent",
restrict: "E",
scope: {
api: '=?'
},
template: "...",
controller: function ( $scope ) {
// I want to access $scope.api in link or controller
},
link: function ($scope, $element, $attr) {
// I want to access $scope.api in link or controller
}
}
});
I can't access $scope.api from the child directive but $scope.parentInstance1 and $scope.parentInstance2 are visible. I realise I can just explicitly declare but I'd rather understand how to do it correctly.
I dont know why you are referencing parentInstance1 and parentInstance2 on my-parent but the attributes on my-child are in myParent's $scope so you can reference the actual $scope.api object that is on myParent's $scope in the attributes of the my-child directive tag and then reference the name of the attribute in the isolate scope definition of the myChild directive.
<my-child inner-api="api"></my-child>
.. and then in the child directive...
app.directive('myChild', function () {
...
scope: {
innerApi: '=?'
}
...
controller: function($scope) {
$scope.innerApi // <- accessible in the controller
}
Heres a simplified fiddle...

Bind directive scope without having controller scope in Angular Js?

html :
<div ng-app="appMod">
<div task-info>{ { data.name } }</div>
</div>
script :
var appmod = angular.module('appMod', []);
appmod.directive("taskInfo", function () {
return {
restrict: 'A',
scope: {},
link: function ($scope, $element, attr) {
$scope.taskdat = '{"name":"Task name","status":"Completed"}';
$scope.data = JSON.parse($scope.taskdat);
scope = $scope; //scope data
},
};
});
is it possible to bind directive scope without having controller scope in Angular Js? If yes, please give me some solution examples.
You don't need a controller scope for writing a directive , see this fiddle.
Here, there is no controller scope, and the value hero is bound within the directive as:
myApp.directive('myDirective', function() {
return {
restrict: 'EAC',
link: function($scope, element, attrs, controller) {
var controllerOptions, options;
$scope.hero='superhero'
}
};
});
Works fine :)
Also the example you provided is similar, but you just need to remove scope from returned JSON object(from directive), as it is being defined as $scope inside the link fucntion.
see : http://jsfiddle.net/bg0L80Lx/
controller option ?
.directive('mydirective', function() {
return {
restrict: 'A', // always required
//controller: 'SomeController'
template:'<b>{{status}}</b>',
controller:'YourCtrl'
}
})

How to bind a transcluded template to a different controller?

I'm trying to pass a template through a directive to a dynamic controller (known at runtime from the directive perspective).
Something like this:
<my-dir ctrl="PersonCtrl">
<h1>{{person.name}} - {{person.age}}</h1>
</my-dir>
var data = {
name: "Alex",
age: "24"
};
function PersonCtrl($scope){
$scope.person = data;
}
myApp.directive('myDir', function($controller){
return {
restrict: "EA",
scope: {
ctrl: "#"
},
transclude: true,
controller: function($scope, $element, $attrs) {
},
template: "<div>{{ctrl}}</div><div ng-transclude></div>",
link: function($scope, $element, $attrs) {
$controller($attrs.foo, {$scope: {}});
}
};
});
see jsFiddle
The controller is found and instantiated, but somehow the binding of the transcluded template to it doesn't work. Do I miss some order requirement or is there a way to bind this controllers scope to the transcluded template?
Found it - should have binded the controller to the $$nextSibling scope!
$controller($attrs.ctrl, {$scope: $scope.$$nextSibling});
updated jsFiddle

Resources