in AngularJS I can define a controller for a section on the page. I can have a single page with multi-controllers.
<div ng-controller="ThisSectionController">
....
</div>
<div ng-controller="ThatSectionController">
....
</div>
I can reuse a controller while sending a different configuration with ng-init
<div ng-controller="MyController" ng-init="i = 1">
{{ i }}
</div>
<div ng-controller="MyController" ng-init="i =2" >
{{ i }}
</div>
This will output 1 and 2 as you expect it.
My question is - How can I reuse a controller and configure it to use a different service?
Create a directive that injects $controller and use it in the linking function to instanciate the controller you want on a map of its instanciation arguments :
$controller("MyController", { $scope: scope, myService: myService})
scope is the scope variable of the linking function and myService is the service you can retrieve with the $injector service.
Related
I want to user a controller for two separated div and when I do that , it send $http requests twice
How can i use the scope of other controllers?
here is my code :
<div data-ng-controller="productCTRL">
<span ng-model="basket | count"></span>
....Some HTML Code......
</div>
<div data-ng-controller="AuthController">
....Some HTML Code...
</div>
<div data-ng-controller="productCTRL">
<ul ng-repeat="product in products">
<li>{{product.title}}</li>
</ul>
</div>
One approach...
You could use a monolithic controller:
<div data-ng-controller="mainCTRL">
<div data-ng-controller="productCTRL">
<span ng-model="basket | count"></span>
....Some HTML Code......
</div>
<div data-ng-controller="AuthController">
....Some HTML Code...
</div>
<div data-ng-controller="productCTRL">
<ul ng-repeat="product in products">
<li>{{product.title}}</li>
</ul>
</div>
</div>
Then if you make the $http call in mainCTRL instead of productCTRL, it will run just once when the view is rendered. You could then access the data held in mainCTRL from productCTRL via scope inheritance.
Another approach...
You could move the $http call to an angular service or factory. Since these are singletons, only one instance will ever exist and that means that only one $http call would be made when the app is first loaded. You would then store the returned data locally in the service and expose it publicly.
Here is a simple implementation as a factory:
app.factory("productService", function($http){
var products = [];
$http.get("api/products/get-products").then(function(response){
products = response.data;
});
return {
products: products
}
});
If you inject the factory into your productCTRL it will have direct access to the products data:
appController("productCTRL", function(productService){
$scope.products = productService.products;
});
The controller will still be instantiated twice, but it's only going to reassign the $scope.products variable. Most importantly, it no longer makes a redundant call over HTTP to your API.
It looks like you want to access the scope of other controllers-
Three are ways to communicate-
Parent child inherited scope - You have to create a parent controller and child controller can communicate using Parent scope. It is recommended only for tightly coupled controllers.
Event bus - Subscribe can listen on event ($on) and publisher can publish using $emit (current to parent scope can access using $on) or $brodcast (current to child scope can access using $on). Sibling controller can't share the data using this approach. To share the data between sibling controller, you can use $rootScope.broadcast and this event will be listen by all scope including sibling controllers. It is also coupled using event.
Using service - Both controller can share the data using common service because services are singleton.
I want to change the iframe source on runtime
<div class="pp lsv-video pp-player" id="rs" ng-controller="ctrl2">
<input type="text" style="width:0px;height:0px;display:none;" />
<iframe src="" class="lsv" marginheight="0" marginwidth="0" frameborder="0"></iframe>
</div>
when user clicks on any of the (mentioned below), teh data mentioned b.VideoSrc should be transferred to the different controller Ctrl2 and iframe source has to be changed.
<ul ng-controller="ctrl1">
<li ng-repeat="b in KeynoteSessions | filter:isBD">
<a href='#rs' class="fancybox" name='{{b.VideoSrc}}'>
<img src='{{b.ImageSrc}}' width='{{b.ImageWidth}}' height='{{b.ImageHeight}}' alt='{{b.ImageAlt}}' /><br />
{{b.Text}}
</a>
</li>
</ul>
please help me to achieve this, thanks!
there are many ways
1.You can create services and use common services to share data.
2.you can use rootscope variable.
3.angularjs $emit, $broadcast methods you can use
like
myApp.factory('Data', function () {
return { FirstName: '' };
});
myApp.controller('FirstCtrl', function ($scope, Data) {
$scope.Data = Data;
});
myApp.controller('SecondCtrl', function ($scope, Data) {
$scope.Data = Data;
});
http://jsfiddle.net/HEdJF/
check this one:Share data between AngularJS controllers
Usually I'm putting related content in the same controller (Youtube frame and "remote" together for exemple) but sometime I can't, so I pass the data through a Javascript Variable (Dont forget that your var need to be defined outside your controller )
I am working on Cordova tool and angularjs for my application.
cordovaApp.controller("VacationCtrl", function ($scope, $http, $location) {
$scope.tempdate = "2222";
$scope.ruleDetails = function () {
$scope.tempdate = "3333";
}
});
view 1
<div ng-controller="VacationCtrl">
<a ng-repeat="data in rules" ng-click="ruleDetails()" class="summaryListBorder" href="#detailVacationRule">
</a>
</div>
view 2
<div ng-controller="VacationCtrl">
{{tempdate}}
</div>
In above given code, I sat value of $scope.tempdate to "2222". When I am click on link, it calls ruleDetails() and set $scope.tempdata = "3333". But when the new page is open with ng-view, it shows only old value, i.e. "2222". I want to change it with "3333". I have tried with $scope.$apply() too.
Thanks.
Every ng-controller attribute creates a new instance of the controller, which won't share the same scope as other instances. You want to wrap both divs in a single controller instance, like:
<div ng-controller="VacationCtrl">
<div>
<a ng-click="ruleDetails()" href="#detailVacationRule">
</a>
</div>
<div>
{{ tempdate }}
</div>
</div>
If you need separate controllers, then you want to move common functions/fields into a service, which operates as a singleton so you can use it to share information between controllers. Or you could contain the separate controller instances in a parent controller, which will hold common fields and can be accessed through each controller's scope.
Here's Plunker
I have an external template within in a controller with ng-include. It is shown and hidden based on click event of Button.It is working as required but with $parent in ng-include Template.Is there any other better way of doing this ?
Html
<body ng-controller="MainCtrl">
<div data-ng-include="'terms.html'" data-ng-show="otherContent"></div>
<div ng-show="mainPage">
<p>Hello {{name}}!</p>
<button data-ng-click="mainPage=false; otherContent=true">Link to some Content</button>
</div>
</body>
JS
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
$scope.mainPage=true;
});
External Template
<p>Some content here </p>
<button data-ng-click="$parent.mainPage=true; $parent.otherContent=false">Back</button>
Option1 - Set property on an object in the scope
In the main controller add an object on the scope.
app.controller('MainCtrl', function($scope) {
$scope.name = 'World';
$scope.page={mainPage:true};
});
and in the ng-click do:-
<div data-ng-include="'terms.html'" data-ng-show="page.otherContent"></div>
<div ng-show="page.mainPage">
<button data-ng-click="page.mainPage=true; page.otherContent=false">Back</button>
<!-- -->
<button data-ng-click="page.mainPage=true; page.otherContent=false">Back</button>
Demo - setting property on an object in the scope
Option2 - Use function
Instead of setting properties on the view (Which is anyways a good idea to abstract out too much logic from the view), Do your set operations in the controller exposed as a function that can be invoked from the view, which also gives extensibility when you need to add more logic for that particular action. And in your case you could even use the same function and call it from both the button clicks and flipped based on a boolean argument.
Demo - with function
Option3 - Use Controller Alias
Using an alias for the controller, which is nothing but instance of the controller is set as a property on the scope with the property name same as the alias provided. This will make sure you are enforce to use dot notation in your bindings and makes sure the properties you access on the child scopes with the controller alias are inherited as object reference from its parent and changes made are reflected both ways. With angular 1.3, it is also possibly to set the isolate scoped directive properties are bound to the controller instance automatically by setting bindToController property in the directive configuration.
Demo - With Controller alias
ControllerAs is the recommend way of avoiding this problem.
Using controller as makes it obvious which controller you are accessing in the template when multiple controllers apply to an element.
If you are writing your controllers as classes you have easier access to the properties and methods, which will appear on the scope, from inside the controller code.
Since there is always a . in the bindings, you don't have to worry about prototypal inheritance masking primitives.
<body ng-controller="MainCtrl as main">
<div data-ng-include="'terms.html'" data-ng-show="main.otherContent"></div>
<div ng-show="mainPage">
<p>Hello {{main.name}}!</p>
<button data-ng-click="main.mainPage=false; main.otherContent=true">Link to some Content</button>
</div>
</body>
Here are some resources for controller as:
http://www.johnpapa.net/angularjss-controller-as-and-the-vm-variable/
http://toddmotto.com/digging-into-angulars-controller-as-syntax/
https://docs.angularjs.org/api/ng/directive/ngController#example
My HTML
ng-app and ng-controller are specified in markup earlier
<div class="statusEntry" ng-repeat="statusInput in statusInputs">
<span class="userName"> a </span>
<span class="statusMsg"> b </span>
</div>
Controller
app.controller('globalCtrl', ['$scope', function($scope) {
//someWork
pubnub.subscribe({
channel: "statuses",
callback:
function (data) {
splitData = data.split(';');
prepData = '{'+splitData[0]+','+splitData[1]+'}';
statusInputs.push(prepData);
}
});
When I push the data no new object appears.
Your Controller has no name.
You haven't declare an ng-app or ng-controller in your markup anywhere.
data should be named $scope so Angular can appropriately inject the dependency.
It doesn't look like either statusInputs or your function are part of the $scope therefore there's no way for your view to access them.
Replace
statusInputs.push(prepData);
with
$scope.statusInputs.push(prepData);
This is how you enable your views to access them.