I want two different components that share the same controller.
But I want to add an extra method for each component and only have that method available when that component is being used.
I'm trying to do something like this.
app.component('myComponent',{
templateUrl: 'mytemplate.html',
controller: 'myController', ['myService', function(myService){
//extra things here
}]
});
Then my second component would be similar, but would do something else inside the controller method.
I know this doesn't work, but is there a way to make this work? or a better way to make this work.
Thank you in advance.
try to use $broadcast subscription
take a look here
https://toddmotto.com/all-about-angulars-emit-broadcast-on-publish-subscribing/
Related
Is there any problem in calling a controller element inside a component element?
Something like this:
angular.module('myApp.bandeja_entrada', [...])
.component('MyComponent', {
templateUrl: 'my_component/my_component.html',
controller: 'MyController',
})
.controller('MyController' , [ ... ]);
No, there is no Problem with that. In Fact, i personally find it better to define my Component Controller this way, because:
A.) Use it in multiple Places
This way you are actually defining an Angular Controller, and therefore its available in the whole Module. So you might will have an use case where you need to use your Controller in several places. With this approach, you can easily use the Controller in multiple places. Once for a component, and maybe once in a "regular" view.
B.) File Structure
I really like to separate my Controller/Component definition. So I have a File with the Component definition and its routing stuff, and another for the Controller. If you declare the Controller Function as an Angular Controller, this makes it really clean.
Both ways are perfectly fine, so just pick the one which is more suitable for you!
I hope everyone doing great.
I have one controller with couple of views. What I want is when I delete some notification from List A, then the model of List B should be updated.
The best & optimized solution for this problem?
One way is that I make a service and shared the list model with both controller. But is there any other best way?
Either you share the data via a service or factory as you mentioned. Or you can use $rootScope.$broadcast events to communicate between the instances of the controller.
Another way is to have the state in a parent scope, and then pass that state down to both its children via attributes on the component/directive. E.g.
<my-first-directive shared-data="sharedData"></my-directive>
<my-second-directive shared-data="sharedData"></my-directive>
This way you can make the recieving directives/components stateless.
1. you can share rootscope variables for the list view.
Using RootScope Variables and Functions are not professional
2. you can use one controller for both views.
If the codes of two views are not much, you can use one controller for both views.
I guess, the best way is not to create two same views for different components. As for me, better practice is using angular routing, so you can use one state through different routes:
$stateProvider.state("my_state", {
url: "/myView",
templateUrl: "/views/my-view.html",
controller: "MyCtrl"
});
P.S. Don't use $rootScope for this purposes, it's not good practice!)
Try to do this way.
.when('/company/ticket/log/:company_id', {
templateUrl: 'views/company/company_ticket_log.html?v=' + CONFIG.VER,
data: {
authorizedRoles: [USER_TYPES.LOGINUSER]
}
});
When you try to do this, use list data in url and list data can be in shared controller like const.js
I try to write my first component. Actually, I refactor one of my previous webpage to use more of the AngularJS functionality.
I use AngularJS 1.5.8
Honestly I always got the following inject error:
http://screencast.com/t/xpyVqSjwUxU
Here is my component code:
http://screencast.com/t/zMaED5ZfZ
The error only came up, when I add the component.js file in index.html with a script tag.
Any idea, what I'm gonna mess? I read the component angularjs documentation but not find the error.
Try putting the return value { templateUrl: ..., controller..., etc } in the .component() function.
angular
.module('Profile')
.component('UpdatePasswordComponent', {
templateUrl: '/modules/profile/update-password/update-password.component.html',
controller: UpdatePasswordController,
controllerAs: 'vm'
});
Another option might be to just change this line
.component('UpdatePasswordComponent', Component)
to
.component('UpdatePasswordComponent', Component())
which will actually call and return the object, but I'm not positive on this one.
I found myself annoyed when I need to specify which controller to use for a template every time I use it for a route or a directive. It get worse when template coupled to a controller with controllerAs syntax, and I have to remember which name it has to be.
$routeProvider.when('/', {
templateUrl: 'stateTemplate.html',
controllerAs: 'ctrl',
controller: 'StateController'
});
ngDialog.open({
template: 'stateTemplate.html',
controller: "StateController",
controllerAs:"ctrl"
});
I’d rather prefer to specify ng-controller StateController as ctrl in the template and totally skip controller and controllerAs in the other places.
The question is: does this approach has some pitfalls I don’t see now? Why it's bad (if it is)? Are the benefits of explicit controller and controllerAs parameters against using ng-controller in the corresponding template? Where canI learn more about it?
I think a lot of people are misunderstanding your question. Am I correct in paraphrasing it as:
What is wrong with only defining a view in your Route Config and then binding that view to a controller using ng-controller="StateController as ctrl"?
So instead of your examples above you would have:
$routeProvider.when('/', {
templateUrl: 'stateTemplate.html',
});
ngDialog.open({
template: 'stateTemplate.html',
});
Then in your stateTemplate.html you would have something like:
<div ng-controller="StateController as ctrl">
<h1>State</h1>
. . .
</div>
Is this what you are asking?
If so, nothing is wrong with this. You will lose the ability to reuse controllers with different views. But honestly that might not be a real concern.
If you use bindToController in directives (you should) you will still want to declare the controller in the Directive Data Object rather than use ng-controller. bindToController causes the property to be bound to the controller before the controller is instantiated.
The other thing you will lose out on is controller dependancy resolve objects.
With uiRouter and ngRouter you can use a resolve object that will then get passed into the controller when the dependancies are resolved. For instance you do not want to display the user details page until the call to get the user details has been returned. Once it is returned it can be passed into the constructor of the controller. This is another thing you will lose out on using with ng-controller. https://github.com/johnpapa/angular-styleguide#resolving-promises-for-a-controller
I am sure there are other benefits to using the declared controllers in the route config. Maybe someone else will point them out.
That said, there is nothing wrong with using it. You should probably be consistent with it so that your code is predictable. If you choose to use ng-controller, it may not not be a big deal to change it in the future. Especially if you have protractor web tests set up so that you know you haven't broken anything.
The quickest answer - bad.
You cannot define business logic inside controller template. What if you need to use now 30 different controllers? are you going to specify 30 different controllers? It's messy, it's unadvised and it's a bad practice all together.
It's like writing BLL inside the input logic layer, or authentications in client side code. You are just making it hard on yourself here.
Defining controllers in templates is defiantly not the answer you are looking for.
I want to expose some of my directive's functionality through its controller (think a public API for this directive).
return {
restrict: 'E',
scope: {},
controller: function($scope) {
this.method1 = ...;
this.method2 = ...;
},
controllerAs: 'dir',
link: function (scope, element, attrs) { ... }
}
Then in my parent controller or template call dir.method1 to get stuff accomplished inside the directive. Any ideas if this is possible as of Angular 1.3?
I'd like to refrain from event passing or even function passing, I have heard this is possible although I have never seen an implementation of this.
It is possible, but your issue isn't to figure out how to get the API out. It's how to get TO it from the parent. You're creating an isolate scope through your use of the 'scope' option. You're also making an element-type directive, so I'm guessing you're doing something like this:
<my-parent>
<my-child></my-child>
</my-parent>
where <my-parent> is the parent directive, and <my-child> is the directive with the API you want to expose.
The real question is what you're trying to achieve here. There is totally a way to do what you're asking. Just because the scope is isolated doesn't mean you can't get to it. You can just iterate through the parent $scope's $$childHead/etc list to find the child whose API you want to access. Anything you define in the child like this:
$scope.myApiFunction = function() {
};
will be visible here. (Things you put into 'this' will not - use the $scope storage bucket instead.)
That means if you only had ONE child you could do something like this from the parent controller:
$scope.$$childHead.myApiFunction();
Simple. Also, very crude. There are lots of problems here: what if you have many children? What if this child with its API ends up one level down? Etc. It's breaking all kinds of OO patterns and it's going to get messy, fast.
Your question is very abstract - it might be good if you updated it with an exact example. Without that, let me guess at your goal. There are two ways to do something "like this" that are encouraged within Angular:
Services. Whenever you say "API", think Service first. A service is a singleton (automatically) so it's tailor-made for creating APIs. And services can use the Factory pattern to return objects of a type, so THOSE are tailor made for doing things like having a manager service handle, say, a buddy list in an IM client, with API methods for creating, removing, and finding buddies.
Items that add "optional" functionality to their parents when they're defined. Let's say we have three possible types of tooltips: tooltips that have a hover effect, those that have a click effect, and those that are triggered by a "walkthrough" system in some order. For this kind of thing, the easy thing to do is just reverse the API, like this:
Parent Controller:
$scope.tooltipHandler = {
showTooltip: function() {},
hideTooltip: function() {}
};
Child Controller:
$scope.$parent.tooltipHandler = {
showTooltip: function() {
// Do some real work
},
hideTooltip: function() {
// Do some real work
},
}
What happens here is if there's no tooltip defined, when the parent runs its walkthrough, nothing happens. If you add the blue tooltip display module, when the parent runs its walkthrough now, it's going to show blue tooltips.
Make sense?
I arrived here looking for a similar response. So far the best that I can figure is to do what Angular does with ngForm.
In the documentation clearly states
If the name attribute is specified, the form controller is published onto the current scope under this name.
This basically makes the form controller accessible from anywhere.
If you have the following DOM
<div ng-controller="MyCtrl as parentCtrl">
<form name="parentCtrl.frmCtrl">
<my-child-directive>
</form>
</div>
You can use require: 'ngForm' in my-child-directive to get access from an inside directive. If you are in the parent controller you can access it trough the frmCtrl variable.
Not sure if this is best practice. In ngForm the name attribute works well, but I don't even know how to call such an attribute for a custom directive.
Thats why I arrived here, I wanted to know if this is "The Angular way" and what types of convetions are on the subject.
Hope it helps!