Angularjs - Calling only one of many subcontrollers/ multiple controllers - angularjs

I have an index page wherein I define two controllers. I want to call one main controller always (should be rendered always) and the other is called only for specific sub URL calls. Should I make one nested within another, or I can keep them independent of each other? I don't have access to change routes or anything, only the controller.
Right now when I use the template (HTML) mentioned, it calls/renders both controllers, even though url is say /index
Only for /index/subPage, I want both controllers to be rendering.
/index
/index/subPage
HTML:
<div ng-controller="MainCtl" ng-init=initMain()>
<p> Within ctller2 {{results}} </p>
</div>
<div ng-controller="Ctller2"> <!-- should not be displayed unless /subPage/mainUrl is rendering -->
<p> Within ctller2 {{results}} </p>
</div>
JS:
app.controller('MainCtl', ['$scope', '$http', '$location', function ($scope, $http, $location) {
$http.get('xx/mainUrl').then(function(data) {
$scope.results = someDataJSON;
console.log(someDataJSON);
});
$scope.initMain = function() {
$scope.initMethods();
}
}]);
app.controller('Ctller2', ['$scope', '$http', '$location', function ($scope, $http, $location) {
// This controller gets initialized/rendered/called even when xx/mainUrl is called, and when xx/subPage/mainUrl is called too..
$http.get('xx/subPage/mainUrl').then(function(data) {
$scope.results = someDataJSON;
console.log(someDataJSON);
})
$http.get('xx/subPage').then(function(data) {
$scope.results = data.data;
console.log(data);
})
angular.element(document).ready(function () {
alert('Hello from SubCtl, moving over from main controller to here');
});
}]);
What am I doing wrong? I'm new to Angular.js

You can conditionally initiate a controller using ng-if. So you could try something like this:
<body ng-controller="MainCtrl">
<div ng-controller="ctrl1">{{hello}}</div>
<div ng-controller="ctrl2" ng-if="showCtrl2">{{hello}}</div>
</body>
and then set the value of the variable in a parent controller by checking the current url using $location.path()
var app = angular.module('plunker', []);
app.config(function($locationProvider){
$locationProvider.html5Mode(true);
});
app.controller('MainCtrl', function($scope, $location) {
$scope.showCtrl2 = ($location.path() === 'my path');
});
app.controller('ctrl1', function($scope){
$scope.hello = 'ctrl1 says hello';
});
app.controller('ctrl2', function($scope){
$scope.hello = 'ctrl2 says hello';
});
But it's a bit hacky and for a larger project a more robust solution would require using something like ui.router.

Related

controller use $scope? custom service use this?

I found in Controller, we use $scope, here is the link (http://www.w3schools.com/angular/tryit.asp?filename=try_ng_controller).
I change $scope to this, it cannot work.
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.firstName = "John";
$scope.lastName = "Doe";
});
</script>
However, I found in Service, we use this, here is the link (http://www.w3schools.com/angular/tryit.asp?filename=try_ng_services_custom).
In hexafy service, I change this to $scope, it cannot work.
<script>
var app = angular.module('myApp', []);
app.service('hexafy', function() {
this.myFunc = function (x) {
return x.toString(16);
}
});
app.controller('myCtrl', function($scope, hexafy) {
$scope.hex = hexafy.myFunc(255);
});
</script>
Does my above summary correct? If not, what should be correct summary considering all kinds of possible.
You can use this instead of $scope in controller as well. They have brought in controller as syntax(from Angular 1.2). You can attach data to this(Here controller holds the data). But internally it will be attached to $scope only, but you don't have to attach it manually. It has to be declared in html like this , controller is declared as main , so we have to refer to data in html using main.
<div ng-controller="MainCtrl as main">
{{ main.title }}
</div>
app.controller('MainCtrl', function ($scope) {
this.title = 'Some title';
console.log("Title" + $scope.main.title); // It will print some title in the console.
});

$rootScope in AngularJS stays UNDEFINED in Controller despite injection?

It's a small ionic / angularJS project for a mobile app.
I am trying to read a JSON file in the same folder as index.html, then assigning it to a $rootScope variable in the RUN segment and then retrieving the $rootScope variable value in a controller. But it's simply not working despite service injections and all.
This is my JSON file:
{"docs":[{"Name":"Alfreds Futterkiste","City":"Berlin","Country":"Germany"},
{"Name":"Ana Trujillin Moreo","City":"México D.F.","Country":"Mexico"}
]
}
This is my app.js / script.js:
angular.module('starter', ['ionic'])
.run(function($ionicPlatform, $rootScope, $http) {
$ionicPlatform.ready(function() {
$rootScope.myDocs = $http.get("/customers.json")
.success(function (response) {
return response.docs;
});
});
})
.controller('MyCtrl', ['$scope', '$rootScope', function($scope, $rootScope) {
$scope.myDocs = $rootScope.myDocs;
//$scope.myDocs = [{'Name': 'a1'},{'Name': 'b1'},{'Name': 'c1'}];
$scope.myStr = JSON.stringify($rootScope.myDocs);
}])
This is the relevant portion from my index.html:
<body ng-app="starter">
<ion-pane>
<ion-header-bar class="bar-stable">
<h1 class="title">Ionic Blank Starter</h1>
</ion-header-bar>
<ion-content ng-controller="MyCtrl">
<ion-list>
<ion-item ng-repeat="x in myDocs">
{{x.Name}}
</ion-item>
</ion-list>
</ion-content>
</ion-pane>
</body>
I have seen other similar examples here but this is still not working and I been banging my head against the wall to achieve a very simple thing.
Fast help is much appreciated.
Here is the Plunker: http://plnkr.co/edit/zx9ANUzCYVvosZFiPSGY?p=info
You're having a timing issue because of ionicPlatform.ready and you aren't using the $http promise correctly.
This is one way to do it:
.run(function($rootScope, $http) {
// $http returns a promise, not the value
$rootScope.docPromise = $http.get("/customers.json")
.then(function(response) {
return response.docs;
});
})
.controller('MyCtrl', ['$scope', '$rootScope', function($scope, $rootScope) {
// you get the value within a .then function on the promise
$rootScope.docPromise.then(function(result) {
$scope.myDocs = result;
})
}])
It is unlikely that you need to make this http call within ionicPlatform.ready. If you don't need to, then it is only delaying the call for no benefit. If for some reason you do need to make the call within the ready function, there are numerous ways to solve this. Here is one example:
// inject $q service
var deferred = $q.defer();
$rootScope.docPromise = deferred.promise;
$ionicPlatform.ready(function() {
$http.get(etc).then(function(response) {
deferred.resolve(response.docs);
});
});
// use $rootScope.docPromise as in the previous example
You might be assuming that the return value from the success method on $http.get() will be assigned to myDocs property on $rootScope but it doesn't work that way. $http.get() is an Asynchronous operation and the success callback will be invoked once the response is available. Also the return value from your success callback is not assigned because it happens sometime in the future.
You need to update your ready() like below.
$ionicPlatform.ready(function() {
/* get will return a promise, cache it in on rootScope for use in controller*/
$rootScope.httpPromise = $http.get("/customers.json");
});
In your Controller
.controller('MyCtrl', ['$scope', '$rootScope', function($scope, $rootScope) {
$rootScope.httpPromise.then(function(response){
$scope.myDocs = response.data.docs;
});
}]);

how to send the data of a ng-controller to another jsp page when click on send button?

Here i will add the product data from response of http for myctrl then when i click on checkout i have to bind all this information and send it to another jsp page in that page i have to get the response data.How can i achieve it by using angularjs. please help me out
<div ng-app="MyApp" ng-controller="MyCtrl">
<div ng-repeat="x in names">
<div>Product Name : {{x.itemname}}</div>
<div>Qty : {{x.itemQty}}</div>
<div>Price : {{x.itemQty}}</div>
<div>Total : {{x.itemQty}}</div>
</div>
<div><button ng-click="checkOut()" >CheckOut</button></div>
</div>
<script>
angular.module("MyApp",[])
.controller("MyCtrl", ['$scope', '$http', function($scope, $http) {
$http.get('responseData.html').success(function(response) {
$scope.names= response;
});
}]);
</script>
Whenever you want to persist the any object/value on client side, I'd suggest you to don't redirect the user to other page.
Instead do create a SPA, add route based view to your application. For implementing such a powerful SAP you could use angular-route API designed by angular team OR you could also use ui.router which is developed by angular-ui team. Suppose you choose angular-route here then, show different view on different routes, you need to configure you route in angular config phase using $routeProvider & then load view and controller for partial view. In your case it would be confirmation submit page on click of button.
You could have one wrapper div on your ng-view directive and then give mainCtrl controller to it. That will act as a sharing component amongest your various views.
HTML
Controller
var app = angular.module('app', ['ngRoute']);
app.config(function($routeProvider) {
$routeProvider
.when('/view1', {
templateUrl: 'view1.html',
controller: 'CustomerDetailsController'
})
.when('/view2', {
templateUrl: 'view2.html',
controller: 'form2Ctrl'
})
.otherwise({
redirectTo: '/view1'
});
});
app.controller('mainCtrl', function($scope) {
$scope.form = {}; //this is global and thats why it can be available on any view
});
app.controller('CustomerDetailsController', function($scope,$location) {
$scope.submit = function(){
if($scope.form1.$valid)
$location.path('/view2');
};
});
app.controller('form2Ctrl', function($scope,$location) {
//this controller contain the data which will you get from
});
Preferable approach for sharing a data would be using singleton service/factory in your application.
HTML
<div class="forms">
<ng-view></ng-view>
</div>
app.service('sharedData', function() {
var sharedData = this;
sharedData.myData = {};
});
app.controller('CustomerDetailsController', function($scope,$location, sharedData) {
$scope.submit = function(){
sharedData.myData.formData = $scope.form1Data; //form1Data will have form1Data
if($scope.form1.$valid)
$location.path('/view2');
};
});
app.controller('form2Ctrl', function($scope,$location, sharedData) {
console.log(sharedData); //this will have the data shared from the CustomerDetailsController
});
For more info Refer this SO Question, Thanks.

How to resolve main controller first then its child controller

I have a controller as main controller and a its child controller. I want to execute first the main controller and then after its child controller.
I am collecting some userdata and want to keep it in $rootScope so that i could access it within the whole application.
How could i do this ?
<body ng-app="angularApp">
<div ng-controller="MainAppController">
<div ng-controller="childController">
Here i want to access data from "MainAppController" stored in $rootScope
But problem is "childController" runs before "MainAppController"
</div>
</div>
</body>
Here is the angular code
angular.module('MyApp').controller('MainAppController', function($rootScope, service){
$rootScope.userData = [];
service.getUserData().success(function(userDetails){
$rootScope.userData = userDetails;
});
});
angular.module('MyApp').controller('childController', function($scope, $rootScope){
$scope.userInfo = $rootScope.userData;
//Here $scope.userInfo is null because $rootScope.userData gets assigned to $scope.userInfo in this controller before userDetails gets assigned to $rootScope.userData in MainAppController controller.
I want that untill "$rootScope.userData = userDetails;" is not finished , "$scope.userInfo = $rootScope.userData;" must not run.
How can i do this ?
});
There are two ways i know you can do this.
1 way ::
Use $rootScope.userData directly in html and when your parent controller will run $rootScope.userData will get updated and by dual binding feature of angular, your view will get updated accordingly
Code::
//angularjs Code
var app = angular.module('MyApp', []);
app.controller('MainController', function($rootScope, $timeout) {
$rootScope.userData = {};
$timeout(function() {
$rootScope.userData = {name:'myName'};
}, 3000);
});
app.controller('childController', function() {
});
//html code
<div ng-app="MyApp" ng-controller="MainController">
<div ng-controller="childController">
{{userData.name}}
</div>
</div>
2 way::
You can attach $watch on $rootScope.userData in childController so when $rootScope.userData will get updated $watch will run and inside $watch you can update your $scope variable
Code::
//Angularjs Code
var app = angular.module('MyApp', []);
app.controller('MainController', function($rootScope, $timeout) {
$rootScope.userData = {};
$timeout(function() {
$rootScope.userData = {name:'myName'};
}, 2000);
});
app.controller('childController', function($scope, $rootScope) {
$scope.$watch(function(){
return $rootScope.userData;
}, function(){
$scope.userInfo = $rootScope.userData;
});
});
//HTML Code
<div ng-app="MyApp" ng-controller="MainController">
<div ng-controller="childController">
{{userInfo.name}}
</div>
</div>

cannot access $scope variables in controller - AngularJS

I created an Angular app that uses Bootstrap. I based the project on a template that I downloaded and studied. I downloaded it from here: https://angularstart.codeplex.com
I did not use or modify the template to create the project that I have now. Instead, I created a new project and used Nuget to download the latest packages for Angular & Bootstrap.
The problem is in my 'Contact' page, which has a form for site visitors to send me a message. I have defined a function - sendMessage - inside the controller which is bound by ng-click to a button in the HTML.
appRoot.controller('ContactController', ['$scope', '$http', function ($scope, $http) {
$scope.contactModel = {};
$scope.sendMessage = function () {
alert('msg: ' + $scope.contactModel.msgSubject);
}
}]);
<input type="text" id="msgSubject" name="msgSubject" data-ng-model="contactModel.msgSubject" />
<button class="btn btn-primary" ng-click="sendMessage()" >Send Message</button>
The button and click event works fine but inside the function, it cant access the model variable. It returns with an 'undefined' - the alert says "msg: undefined"
I've researched this for three days now. I've looked at other demo code on plunkr and jsfiddle and I've seen it work but something in my setup prevents access to the scope variables (basically my defined model vars).
My angular app.js is:
var appRoot = angular.module('main', ['ngRoute', 'ngResource']);
appRoot
.config(['$routeProvider', function ($routeProvider) {
$routeProvider
.when('/', { templateUrl: '/main/home', controller: 'HomeController' })
.when('/home', { templateUrl: '/main/home', controller: 'HomeController' })
.when('/contact', { templateUrl: '/main/contact', controller: 'ContactController' })
}])
.controller('RootController', ['$scope', '$route', '$routeParams', '$location', function ($scope, $route, $routeParams, $location) {
$scope.$on('$routeChangeSuccess', function (e, current, previous) {
$scope.activeViewPath = $location.path();
});
}]);
I've tested adding the variable when initializing the contactModel variable:
$scope.contactModel = { msgSubject: 'tst sub' };
The alert inside the 'sendMessage' function sees this and shows "msg: tst sub" correctly.
I've tried different configurations for the ContactController, including passing $location and $resource like so:
appRoot.controller('ContactController', function ($scope, $location, $resource) {
}
but still can't access the scope variables.
In all the samples & demos I've checked out - including the Angular Start tempate - the controller can access the defined ng-model variable. Makes me think it has to be in my configuration or use of the differnt versions of either Angular or Bootstrap.
My _Layout.cshtml defines the default controller and ng-app as so:
<body data-ng-app="main" data-ng-controller="RootController"style="background-color:transparent;" >
Angular version is v1.2.2 and Bootstrap is v3.1.0
Any help is apporeciated. Thanks
I think I've narrowed it down. I'd like to add that I am also using ASP.NET MVC with Razor.
If I put the HTML code outside the #RenderBody() and I put the javascript alert inside the RootController, the code works:
<div >
<div>
<input type="text" id="msgSubject" name="msgSubject" data-ng-model="contactModel.msgSubject" />
<button class="btn btn-primary" ng-click="sendMessage()" >Send Message</button>
</div>
</div>
<div >
#RenderBody()
</div>
And the Javascript:
app.controller('RootController', ['$scope', '$route', '$routeParams', '$location', function ($scope, $route, $routeParams, $location) {
$scope.$on('$routeChangeSuccess', function (e, current, previous) {
$scope.activeViewPath = $location.path();
});
$scope.contactModel = {};
$scope.sendMessage = function () {
alert('msg: ' + $scope.contactModel.msgSubject);
}
}]);
If the HTML is inside the partial view (cshtml), the Angular controller does not see the scope variable as defined by ng-model.
Perhaps Angular execution is blocked by ASP.NET MVC's Razor engine? Something's going on in the #RenderBody() that is probably stripping the functionality out..

Resources