Use scope from multiple controllers on page - angularjs

So i've split out my UI into subcomponents but then i realise that one of the components requires to be react to a dropdown change which is caught by the parent controller.
I can create a shared service for the variables and i have been able to inject the sub controller so that i can kick off functions BUT.
how do i then use the scope within the sub controller?
var ctrl1= $scope.$new();
$controller('ctrl', { $scope: ctrl1});
ctrl1.GetData();
this works fine. I can see data coming back in the console. BUT my ui doesnt change. What am i missing?
I've edited the post to illustrate what i'm attempting to do more clearly.
The drop down on change is caught by the parent controller but i then require the child controller to run away and get some data and update the UI.
It's an attempt to split out the components. Is this possible? Or have a split the components out too far?
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0/angular.min.js"></script>
<script>
angular.module('app2', [])
.controller('ctrl2', ['$scope', '$http', function($scope, $http){
$scope.getdata = function(){
$http.post(WebServiceURL)
.success(function(data){
$scope.app2Data = "test2 data";
});
}
}]);
angular.module('app1', ['app2'])
.controller('ctrl1', ['$scope','$controller',function($scope, $controller){
$scope.name = 'Controller 1';
//just something to put in the ddp
$scope.data = [
{id:1, name: "test"},
{id:2, name: "test2"}
]
$scope.makeChanged = function(id){
//ddp has changed so i refresh the ui with some other data which is in got by ctrl2.
var cl2 = $scope.$new();
$controller('ctrl2', { $scope: cl2 });
cl2.getdata();
}
}]);
</script>
</head>
<body ng-app="app1">
<div ng-controller="ctrl1">
<p>here is: {{name}}</p>
<select ng-model="d" ng-options="d as dat.name for dat in data track by dat.id" ng-change="makeChanged(d.id)"></select>
<div>
{{app2Data.text}}
</div>
</div>
</body>
</html>

for anyone interested here's how i got round this.
I created a shared service between the two controllers. and created a callback on the service. i registered the call back on ctrl2 so when the shared variable changed the controller2 will do what i want it to and scope is freshed.
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0/angular.min.js"></script>
<script>
angular.module('app1', ['app2'])
.controller('ctrl1', ['$scope', '$controller', 'appointmentSharedProperties',
function($scope, appointmentSharedProperties) {
$scope.name1 = 'Controller 1';
console.log('ctrl1');
//just something to put in the ddp
$scope.data = [{
id: 1,
name: 'test'
}, {
id: 2,
name: 'test2'
}];
$scope.makeChanged = function(value) {
//ddp has changed so i refresh the ui with some other data which is in got by ctrl2.
appointmentSharedProperties.setDetail(value);
console.log('in makeChanged: ' + value);
}
}
]).service('appointmentSharedProperties', function() {
var test = '';
var __callback = [];
return {
getDetail: function() {
return test;
},
setDetail: function(value) {
test = value;
if (__callback.length > 0) {
angular.forEach(__callback, function(callback) {
callback();
});
}
},
setCallback: function(callback) {
__callback.push(callback);
}
};
});
angular.module('app2', [])
.controller('ctrl2', ['$scope', 'appointmentSharedProperties',
function($scope, appointmentSharedProperties) {
$scope.name2 = 'Controller 2';
console.log('ctrl2');
var getdata = function() {
console.log('in getdata');
$scope.app2Data = appointmentSharedProperties.getDetail();
}
appointmentSharedProperties.setCallback(getdata);
}
]);
</script>
</head>
<body ng-app="app1">
<div ng-controller="ctrl1">
<p>here is: {{name1}}</p>
<p>here is: {{name2}}</p>
<select ng-model="d" ng-options="d as dat.name for dat in data track by dat.id" ng-change="makeChanged(d.name)"></select>
<div>
{{app2Data}}
</div>
</div>
</body>
</html>

General example of how to pass variables from one controller to other
<html>
<head>
<meta charset="ISO-8859-1">
<title>Basic Controller</title>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js">
</script>
</head>
<body ng-app="myApp">
<div ng-controller="ctrl1">
{{greeting}}
</div>
<div ng-controller="ctrl2">
{{dataToHtml2}}
</div>
</body>
</html>
This is the javascript file for this
var myApp = angular.module('myApp',[]);
myApp.service('sampleService', function(){
var temp = '';
this.setValue = function(data){
temp = data;
}
this.getValue = function(){
return temp;
}
});
myApp.controller('ctrl1', function($scope,sampleService) {
$scope.greeting = 'This line is in first controller but I exist in both';
var data= $scope.greeting;
sampleService.setValue(data);
});
myApp.controller('ctrl2', function($scope, sampleService){
$scope.dataToHtml2 =sampleService.getValue();
});
Here is the blog that explains this flow : Frequently asked questions in angularjs
It has the demo of what I written. Happy coding..!!

Related

pass date between two controllers using rootscope angular js

i am using $rootScope to share my values. please check my code
user controller (user.js)
var app = angular.module('myApp', []);
app.controller('user', function($scope,$rootScope) {
$rootScope.test = "TEST";
});
customer controller (customer.js)
app.controller('customer', function($scope,$rootScope) {
$scope.value = $rootScope.test;
alert($scope.value);
});
this code seems to be ok. but result is undefined. i need to keep all data inside the controller also.
my result
how i pass this value correctly
Instead of user $rootScope to share some data between those controllers, you could also use a service. Here is an example :
(function () {
'use strict';
angular.module('app', []);
angular.
module('app')
.service('contextService', [function () {
var context = {
"foo": "bar",
"hello": "boys"
};
var service = {
getContext: function () {
return context;
},
getContextValue: function (key) {
return context[key];
},
setContextValue: function (key, value) {
context[key] = value;
}
}
return service;
}])
.controller('userController', ['$scope', 'contextService', function ($scope, contextService) {
var vm = this;
vm.context = contextService.getContext();
contextService.setContextValue("foo", "baz");
}])
.controller('customerController', ['$scope', 'contextService', function ($scope, contextService) {
var vm = this;
vm.context = contextService.getContext();
vm.updateContext = function (key, value) {
contextService.setContextValue(key, value);
}
}])
})();
<!DOCTYPE html>
<html lang="en" ng-app="app">
<head>
<meta charset="utf-8" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.min.js"></script>
<script src="module.js"></script>
</head>
<body>
<div ng-controller="userController as vm">
<strong>userController</strong>
<pre>
foo = {{ vm.context.foo }}
hello = {{ vm.context.hello }}
</pre>
</div>
<hr />
<div ng-controller="customerController as vm">
<strong>customerController</strong>
<pre>
foo = {{ vm.context.foo }}
</pre>
<button ng-click="vm.updateContext('hello', 'guys')">
Update context <strong>hello</strong> value
</button>
</div>
</body>
</html>

Passing data from one route to another route

It must be able to pass data between route controllers. Like for example have an input field in one route where its contents will be displayed in the next route. I don't want it with $rootScope.
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.name = "John Doe";
});
</script>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
Name: <input ng-model="name">
<h1>You entered: {{name}}</h1>
Click to see this data to another page (route)
</div>
</body>
</html>
See This
RipTutorial -
Handling session storage through service using angularjs
app.factory('storageService', ['$rootScope', function($rootScope) {
return {
get: function(key) {
return sessionStorage.getItem(key);
},
save: function(key, data) {
sessionStorage.setItem(key, data);
}
};
}]);
app.controller('myCtrl',['storageService',function(storageService) {
// Save session data to storageService
storageService.save('key', 'value');
// Get saved session data from storageService
var sessionData = storageService.get('key');
});

AngularJs with REST Api

i'm new to angularJs and want to learn more about it, i'm trying to display some users from a fake REST Api, when trying to run my code i got empty page and the console doesn't give me any errors , i don't know where is the error or where i can debug.
app.js
var myApp = angular.module("app", []);
contactsData.service.js look like that :
(function () {
var app = angular.module("app");
app.service("contactDataSvc", function ($http) {
var self = this;
self.getContacts = function () {
var promise1 = $http.get("http://localhost:3000/contacts");
var promise2 = promise1.then(function (response) {
return response.data;
});
return promise2;
}
});
})();
contacts.controller.js
(function () {
var myApp = angular.module("app");
myApp.controller("contactsCtrl", contactsCtrl);
function contactsCtrl(contactDataSvc) {
contactDataSvc.getContacts()
.then(function(data){
this.contacts = data;
});
}
})();
finally my view index.html
<html ng-app="app">
<head>
<title></title>
<script src="angular.js"></script>
<script src="app.js"></script>
<script src="contacts.controller.js"></script>
<script src="contactsData.service.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" />
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap-theme.min.css" />
<!--<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>-->
</head>
<body class="container">
<div>
<div ng-controller="contactsCtrl as ctrl">
<div class="raw">
<ul class="list-group">
<li class="li-group-item" ng-repeat="obj in ctrl.contacts">
{{obj.name.title + " " + obj.name.first + " " + obj.name.last}}
</li>
</ul>
</div>
</div>
</div>
</body>
</html>
Small correction required in your contactsCtrl
function contactsCtrl(contactDataSvc) {
var vm = this;
contactDataSvc.getContacts()
.then(function(data){
vm.contacts = data;
});
}
You cannot use this inside the then callback as the scope will be different.
Corrected working example here : http://plnkr.co/edit/LLKJipkBbiZ17QjQpw1X
Refer more:
https://www.w3schools.com/js/js_scope.asp
What is the scope of variables in JavaScript?
1 - Is this url correct? http://localhost:3000/contacts
2 - Open the url on any browser, does it return any response ? JSON?
Please check this first to see if the problem is not on the server side.
Firstly inject $scope in controller because anything/data that we want to access over Html from controller needs to be binded on $scope.
So you controller would look like:
(function () {
var myApp = angular.module("app");
myApp.controller("contactsCtrl", contactsCtrl);
function contactsCtrl($scope,contactDataSvc) {
contactDataSvc.getContacts()
.then(function(data){
$scope.contacts = data;
});
}
})();
Secondly from the service you need to return a promise from it only then you will be able to get the data once the response is back from the API.
So,the updated service code is :
(function () {
var app = angular.module("app");
app.service("contactDataSvc", function ($http,$q) {
var self = this;
var defered = $q.defer();
self.getContacts = function () {
var promise1 = $http.get("http://localhost:3000/contacts");
promise1.then(function (response) {
defered.resolve(response.data);
});
return defered.promise;
}
});
})();

angularJS good practise: how to create controllers for complex application?

let assume I need to create a dashboard application that includes users, tasks and messages. I have a theoric knowledge of angularJS only, not real life application and I don't know exactly how to architect an angular application.
<html ng-app="myApp">
<head>
<script src="js/vendor/angular/angular.min.js"></script>
<script src="js/app.js"></script>
</head>
<body>
<div id="users" ng-controller="usersController"></div>
<div id="tasks" ng-controller="tasksController"></div>
<div id="messages" ng-controller="messagesController"></div>
</body>
</html>
and app.js
var myApp = angular.module('myApp', []);
myApp.controller('usersController', function($scope) {
$scope.users = [{id:1, username:'john'},{id:2, username:'jack'}];
});
myApp.controller('tasksController', function($scope) {
$scope.tasks = [];
$scope.addTask = function(userid, task) {
}
});
myApp.controller('messagesController', function($scope) {
$scope.messages = [];
$scope.addMessage = function(userid, message) {
}
});
I just cannot figure out how taskController can speak with usersContoller or Taskcontroller.
Or should I use something like
myApp.users = {};
myApp.tasks = {};
myApp.messages = {};
Or should I use a service for that ?
and finally how to watch for changes on that users, tasks and messages.

Wait for async data before rendering a list on AngularJS and Ionic

I am a newbie on Angular JS but have good experience working with Javascript.
In my App I am creating a simple Factory fulfilled by JSON data coming from a web service:
.factory('Tools', function($http) {
var tools = {content:null};
var promise = $http.get('/Tool/GetTools').success(function(data) {
tools.content = data;
//At this points all the data is on tools.content
});
return {
promise:promise,
all: function(){
return tools;
//At this point tools equals to null
}
}
});
But when I want to render the list:
<ion-list>
<ion-item ng-repeat="tool in tools">
Hello, {{tool}}!
</ion-item>
</ion-list>
The info isn't still there yet.
I have this on my controller:
.controller('AccountCtrl', function($scope, Tools) {
$scope.tools = Tools.all();
});
Is there a way to tell the list to "wait" while the Tools object loads from the ajax call before the list renders?
Thanks!
You have to return from your factory the promise and into controller you can check the success.
Something like this:
(i've simulated the wait with a timeout)
angular.module('App', [])
.controller('Ctrl', function($scope, resultsFactory) {
$scope.results = [{txt: 'Loading..'}];
resultsFactory.all().then(
function(res){
$scope.results = res;
},
function(err){
console.error(err);
}
);
})
.factory('resultsFactory', function($http, $timeout, $q) {
var results = {};
function _all(){
var d = $q.defer();
$timeout(function(){
d.resolve([{txt:'one'},{txt:'two'},{txt:'three'}]);
}, 2000);
return d.promise;
}
results.all = _all;
return results;
});
<!DOCTYPE html>
<html ng-app='App'>
<head>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.20/angular.min.js"></script>
<meta charset="utf-8">
<title>JS Bin</title>
</head>
<body>
<div ng-controller='Ctrl'>
<p ng-repeat='res in results'> {{res.txt}}</p>
</div>
</body>
</html>
You have to say {{tool}}
Its typo :-)
<ion-list>
<ion-item ng-repeat="tool in tools">
Hello, {{tool}}!
</ion-item>
</ion-list>

Resources