I'm quite new to Angular, so I'm pretty sure there's something I'm missing here.
I just read an article about isolated scopes, with expressions in particular using & symbol.
This is the article, which includes a fiddle.
I'm trying to do something more simple, I want to use also a function but don´t want to use a button to do the calling, I'd like to directly call the function. I reduced the code in the fiddle to something similar to what I want but it has no effect, the function is not being called, or it is but is not doing what I expect.
If I uncomment line #12 I 'Hello' is displayed, and if comment then I expected 'as' to be displayed in the textbox, but instead it's cleared. What am I missing here?
Thanks,
PS. I can´t seem to make the snipped work, but the fiddle works fine.
var myModule = angular.module('myModule', [])
.directive('myComponent', function () {
return {
restrict: 'E',
scope: {
isolatedExpressionFoo: '&'
}
};
})
.controller('MyCtrl', ['$scope', function ($scope) {
$scope.foo = 'Hello!';
//$scope.isolatedExpressionFoo();
$scope.updateFoo = function () {
$scope.foo = 'as';
}
}]);
<div ng-controller="MyCtrl">
<input ng-model="foo">
<my-component isolated-expression-foo="updateFoo()" />
</div>
The $scope from the controller and the directive are two different ones. The controller $scope has no access to the isolatedExpressionFoo function.
To instantly call the function provided to your directive (from within the directive) you will need to implement a controller for said directive.
E.g.
var myModule = angular.module('myModule', [])
.directive('myComponent', function () {
return {
restrict:'E',
scope:{
isolatedExpressionFoo:'&'
},
controller: function($scope){
$scope.isolatedExpressionFoo();
}
};
})
.controller('MyCtrl', ['$scope', function ($scope) {
$scope.foo = 'Hello!';
$scope.updateFoo = function () {
$scope.foo = 'as';
}
}]);
Related
I'm trying to write a simple angular service and a factory like below:
html:
<div ng-controller="mycontroller">
{{saycheese}}
</div>
Javascript
var myApp = angular.module('myApp', []);
myApp.service('myservice', function() {
this.sayHello = function() {
return "from service";
};
});
myApp.factory('myfactory', function() {
return {
sayHello: function() {
return "from factory!"
}
};
});
//defining a controller over here
myapp.controller("mycontroller", ["myfactory", "myservice", function(myfactory, myservice) {
$scope.saycheese = [
myfactory.sayHello(),
myservice.sayHello()
];
}]);
But the JSFiddle still just displays {{saycheese}} instead of angular mapping the function.
Link to my fiddle:
http://jsfiddle.net/PxdSP/3047/
Can you point me where am I going wrong in this case ? Thanks.
You have several syntax errors in your code, and checking the console would have helped without questioning the SO. Here's one possible way to write the controller (demo):
myApp.controller("mycontroller", ["$scope", "myfactory", "myservice",
function($scope, myfactory, myservice) {
$scope.saycheese = [
myfactory.sayHello(),
myservice.sayHello()
];
}]);
Apart from obvious fix myapp => myApp (variable names are case-sensitive in JavaScript), $scope should be passed into controller as an argument (and mentioned as its dependency if using arrayed - proper - form of controller definition, as you did) before you can access it. Otherwise you just get ReferenceError: $scope is not defined exception when controller code is invoked.
Couple things:
myapp.controller(...) should be myApp.controller(...)
You need to inject $scope in your controller.
Fixed controller:
myApp.controller("mycontroller", ["myfactory", "myservice", "$scope", function(myfactory, myservice, $scope) {
$scope.saycheese = [
myfactory.sayHello(),
myservice.sayHello()
];
}]);
I'm trying to figure out AngularJS directives. I've got the following JSFiddle with an example of something I'm trying to do. https://jsfiddle.net/7smor9o4/
As you can see in the example, I expect the vm.alsoId variable to be equal to vm.theId. In the template vm.theId displays the correct value but vm.alsoId does not.
What am I doing wrong? How could I accomplish my goal.
If it helps the final idea is to execute something as the following:
function directive(service) {
var vm = this;
vm.entity = null;
init();
function init() {
service.getEntity(vm.theId).then(function (entity) {
vm.entity = entity;
});
}
}
As you've noticed, the bindToController bindings are not immediately available in the controller's constructor function (unlike $scope, which are). What you're looking for is a feature introduced with Angular 1.5: Lifecycle Hooks, and specifically $onInit.
You had the right idea; simply replace your init function definition and invocation as follows:
vm.$onInit = function () {
service.getEntity(vm.theId).then(function (entity) {
vm.entity = entity;
});
};
And here is your updated fiddle.
(Alternatively, without this solution, you'd have needed a watch.)
Angular recommends that you bind a controller "only when you want to expose an API to other directives. Otherwise use link."
Here's a working fiddle using the link function.
angular.module('app', [])
.directive('directive', directive);
angular.element(function() {
angular.bootstrap(document, ['app']);
});
function directive() {
return {
restrict: 'E',
scope: {
theId: '<'
},
template: `
alsoId: <span ng-bind="alsoId"></span>
theId: <span ng-bind="theId"></span>`,
link: link
};
}
function link(scope, element, attrs) {
init();
function init() {
scope.alsoId = scope.theId;
}
}
I am new to using angular js and i have declare many controller and now i want to user function of one controller into another controller. here is my sample code.
app.controller('Controller1',function($scope,$http,$compile){
$scope.test1=function($scope)
{
alert("test1");
}
});
app.controller('Controller2',function($scope,$http,$compile){
$scope.test2=function($scope)
{
alert("test1");
}
});
app.controller('Controller3',function($scope,$http,$compile){
///
});
Now i want to call test2 function inside controller3.
Can anybody help..
Thanks in Avance... :)
You can't call a method from a controller within a controller. You will need to extract the method out, create a service and call it. This will also decouple the code from each other and make it more testable
(function() {
angular.module('app', [])
.service('svc', function() {
var svc = {};
svc.method = function() {
alert(1);
}
return svc;
})
.controller('ctrl', [
'$scope', 'svc', function($scope, svc) {
svc.method();
}
]);
})();
Example: http://plnkr.co/edit/FQnthYpxgxAiIJYa69hu?p=preview
Best way is write a service and use that service in both controllers. see the documentation Service documentation
If you really want to access controller method from another controller then follow the below option:
emitting an event on scope:
function FirstController($scope) { $scope.$on('someEvent', function(event, args) {});}
function SecondController($scope) { $scope.$emit('someEvent', args);}
The controller is a constructor, it will create a new instance if for example used in a directive.
You can still do what you wanted, assuming that your controllers are in the same scope, just do:
Note they must be in the same scope, could still work if a child scope was not isolated.
The directive's definition:
{
controller: Controller1,
controllerAs: 'ctrl1',
link: function($scope) {
$scope.ctrl1.test1(); // call a method from controller 1
$scope.ctrl2.test2(); // created by the directive after this definition
$scope.ctrl3.test3(); // created by the directive after this definition
}
}
....
{
controller: Controller2,
controllerAs: 'ctrl2',
link: function($scope) {
$scope.ctrl1.test1(); // created earlier
$scope.ctrl2.test2(); // ...
$scope.ctrl3.test3(); // created by the directive after this definition
}
}
....
{
controller: Controller3,
controllerAs: 'ctrl3',
link: function($scope) {
$scope.ctrl1.test1();
$scope.ctrl2.test2();
$scope.ctrl3.test3();
}
}
This should work.
JQuery to Directive
I want to call a method from the scope of this directive but can't seem to work it out (if possible).
$("my-directive").first().scope().loadData();
Directive Looks Something Like This
I would like to call the loadData function from the directive code below.
app.directive("myDirective", function () {
return {
restrict: "E",
templateUrl: "..."
scope: {},
controller: function ($scope, $element, $attrs) {
var self = this;
$scope.loadData = function () {
...
};
}
};
});
Scope is accessible inside the directive
You can get any child of the element of which directive is applied and get scope of it.
$('my-directive').first().children(":first").scope().loadData()
Strajk's answer is correct!
When Code is Added Dynamically setTimeout Needed
In the following example detail row has a nested directive (random-testees). I get the scope from that to dynamically compile the directive (dynamic and late-bound). The setTimeout is needed because it seems to take a bit before the
var detailRow = e.detailRow;
// Compile the directive for dyanmic content.
angular.element(document).injector().invoke(function ($compile) {
var scope = angular.element(detailRow).scope();
$compile(detailRow)(scope);
});
// Get some data from directive.
var testId = detailRow.find("random-testees").attr("testid");
// Wait, and call method on the directive.
setTimeout(function () {
var randomTesteesScope = $("random-testees").first().children(":first").scope();
randomTesteesScope.loadTestees(this);
}.bind(testId),200);
Not Very Confident About This
This seems a little brittle since I was getting mixed results with a 100 ms timeout sometimes and error when the randomTesteesScope returned undefined.
I want to have a call back function on a directive I wrote, without creating an isolated scope. The directive simply makes the element resizeable, and thus doesn't need a separate scope (and it's desirable NOT to have isolated scope in this case, I think).
What is the best way to do this? I tried,
.controller("MyController", function ($scope) {
$scope.myFunc = function () {
console.log("test");
};
})
.directive('resizeable', function ($document, $parse) {
return function (scope, element, attr) {
var func = $parse(attr.onFunc);
}
}
with
<div class="main" resizeable="" on-Func="myFunc()">
How to do this?
Try this JSFiddle.
You're close, here is what I'd do:
.directive('resizeable', ['$document', '$parse', function ($document, $parse) {
return {
link: function ($scope, $element, $attrs) {
var func = $parse($attrs.resizeable);
// do stuff...
func($scope);
}
};
}]);
And the HTML would be:
<div data-resizeable="myFunc()"></div>
Here is a working demo: http://plnkr.co/edit/as6Tylj0zPpjVsUaDDC6?p=preview
on-Func="myFunc"
Without parenthesis. And in the directive:
var func = scope[attr.onFunc];
The directive is in the same scope as the controller. So you can directly refernece the function.