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>
I am new in angularjs. I searched a lot to hide some html element on body resize but did't work. here is my controller code.
var app = angular.module('studentPage',[]);
app.controller ('studentController',function($scope, $window) {
var appWindow = angular.element($window);
appWindow.bind('resize', function () {
if($window.innerWidth < 600){
alert("hello");
$scope.ohh = true;
}
});
});
and here where i use ng-show
<div id="sidebar-wrapper" ng-show="ohh">
If you want to achieve this using AngularJS, you need to relaunch the digest cycle using $scope.$apply().
appWindow.bind('resize', function () {
if($window.innerWidth < 600){
$scope.ohh = true;
$scope.$apply();
}
});
Anyway, I think a cleaner way to do that is using CSS media queries:
#media only screen and (max-width: 599px) {
#sidebar-wrapper {
display: none;
}
}
You have to manually trigger the digest cycle using $apply() function , since what you are doing is out of angular context.Try the below code.
var app = angular.module('studentPage',[]);
app.controller ('studentController',function($scope, $window) {
var appWindow = angular.element($window);
appWindow.bind('resize', function () {
if($window.innerWidth < 600){
alert("hello");
$scope.ohh = true;
$scope.$apply()
} });});
You have to apply the scope changes by calling $scope.$apply().:-
var app = angular.module("myApp", []);
app.controller("myCtrl", function($scope, $window) {
var appWindow = angular.element($window);
$scope.ctrl = {};
$scope.ctrl.ohh = false;
appWindow.bind('resize', function() {
console.log($window.innerWidth);
if ($window.innerWidth < 600) {
$scope.ctrl.ohh = true;
$scope.$apply()
}
});
});
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<h1>THis is main content</h1><br>
<div id="sidebar-wrapper" ng-show="ctrl.ohh">This is shown after window width is less than 600
</div>
</div>
I am working on separating some JSON requests out of a controller and into a factory service in angular and sort of have it working. Presently, when I update the data (as with a request for new data) I have to make the request twice to actually see the updated data. I presume, from my presently limited knowledge of Angular that I am missing the promise aspect. However, I am not really sure how best to proceed. Code follows:
(function(angular) {
'use strict';
var myApp = angular.module('weatherApp', [])
.controller('MyWeatherController', ['$scope', '$http', '$log', 'weather', function($scope, $http, $log, weather) {
$scope.city = 'Cincinnati';
$scope.units = 'imperial';
$scope.updateData = function() {
weather.updateData($scope, $http, $log);
};
// Initial run to fetch weather data
$scope.updateData();
}])
// Set up a service factory to fetch current and forecast data
.factory('weather', ['$http', function($http) {
var services = {};
services.updateData = function(scope, http, log) {
this.updateCurrent(scope, http, log);
}
// Get current data
services.updateCurrent = function(scope, http, log) {
// Fetch current weather data from api
var url = 'http://api.openweathermap.org/data/2.5/weather';
http.jsonp(url, {params: {
q: scope.city,
units: scope.units,
callback: 'JSON_CALLBACK'
}})
.success(function(data, status, headers, config) {
scope.main = data.main;
scope.wind = data.wind;
scope.description = data.weather[0].description;
})
.error(function(data, status, headers, config) {
log.error('Could not retrieve data from '+url);
});
};
return services;
}]);
} (window.angular));
body {
width: 50%;
margin: 2em auto;
}
h2 {
background: green;
color: white;
padding: 10px;
margin-bottom: 0;
}
input {
margin-bottom: 1em;
}
.section {
margin-bottom: 2em;
background: #f0f0f0;
padding: 10px;
}
<!DOCTYPE html>
<html>
<head>
<title>Weather checker</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.11/angular.min.js"></script>
<script src="script.js"></script>
<link type="text/css" rel="stylesheet" href="style.css" media="all" />
</head>
<body>
<div class="container" ng-app="weatherApp">
<div ng-controller="MyWeatherController">
<h2>Current weather in {{city}}</h2>
<div class="section current">
<form name="weather-form">
<label for="city">City, State / Zip code</label>
<input
type="text"
ng-model="city"
ng-model-options="{updateOn: 'submit'}">
<br>
<label for="units">Units</label>
<input type="radio" ng-model="units" value="metric"> Metric
<input type="radio" ng-model="units" value="imperial"> Imperial<br>
<button ng-click="updateData()">Update</button>
<h3>{{data.name}}</h3>
<p>{{description}}</p>
<p>Temperature: {{main.temp}}</p>
<p>Wind speed: {{wind.speed}}</p>
</form>
</div>
</div>
</div>
</body>
</html>
As you can tell if you run this, you have to update twice to get the new data to display in the view. Any suggestions on some examples or feedback on next steps would be greatly appreciated!
Thanks
It's because of ng-model-options directive.
City value is not updated in the model till we submit the form.
So, when after changing the city, when we click for the first time, the values are fetched for the old city, which will not reflect any changes in the UI. As this is a submit action this will update the model.
When we click second time, values are fetched with the new city value.
Here is implementation with promise.
Your code with promise would look like this, you shouldn't pass variable like $scope, $http, $log to service they will be easily available inside service by injecting it dependency.
scope variables should not get modified using service, you should return a promise from service and inside the promise success or error you can do modify your scope.
From service I returned $http.jsonp which already has promise so you don't need to care about returning promise, and that promise get resolved inside .success function and you can get reject promise inside .error function
CODE
(function (angular) {
'use strict';
var myApp = angular.module('weatherApp', [])
.controller('MyWeatherController', ['$scope', '$http', '$log', 'weather', function ($scope, $http, $log, weather) {
$scope.city = 'Cincinnati';
$scope.units = 'imperial';
$scope.updateData = function () {
weather.updateData($scope.city, $scope.units).
then(function (res) {
var data = res.data;
$scope.main = data.main;
$scope.wind = data.wind;
$scope.description = data.weather[0].description;
},function (data) {
$log.error('Could not retrieve data from ' + url);
})
};
// Initial run to fetch weather data
$scope.updateData();
}])
// Set up a service factory to fetch current and forecast data
.factory('weather', ['$http', '$log', function ($http, $log) {
var services = {};
services.updateData = function (city, units) {
return this.updateCurrent(city, units);
};
// Get current data
services.updateCurrent = function (city, units) {
// Fetch current weather data from api
var url = 'http://api.openweathermap.org/data/2.5/weather';
return $http.jsonp(url, {
params: {
q: city,
units: units,
callback: 'JSON_CALLBACK'
}
}).success(function (data, status, headers, config) {
return data;
})
.error(function (data, status, headers, config) {
$log.error('Could not retrieve data from ' + url);
return data;
});
};
return services;
}]);
}(window.angular));
Fiddle
Hope this could helpful to you, Thanks.
(function(angular) {
'use strict';
var myApp = angular.module('weatherApp', [])
.controller('MyWeatherController', ['$scope', '$http', '$log', 'weather', function($scope, $http, $log, weather) {
$scope.city = 'Cincinnati';
$scope.units = 'imperial';
$scope.updateData = function() {
weather.updateData($scope, $http, $log);
};
// Initial run to fetch weather data
$scope.updateData();
}])
// Set up a service factory to fetch current and forecast data
.factory('weather', ['$http', function($http) {
var services = {};
services.updateData = function(scope, http, log) {
this.updateCurrent(scope, http, log);
}
// Get current data
services.updateCurrent = function(scope, http, log) {
// Fetch current weather data from api
var url = 'http://api.openweathermap.org/data/2.5/weather';
http.jsonp(url, {params: {
q: scope.city,
units: scope.units,
callback: 'JSON_CALLBACK'
}})
.success(function(data, status, headers, config) {
scope.main = data.main;
scope.wind = data.wind;
scope.description = data.weather[0].description;
$scope.digest();
})
.error(function(data, status, headers, config) {
log.error('Could not retrieve data from '+url);
});
};
return services;
}]);
} (window.angular));
body {
width: 50%;
margin: 2em auto;
}
h2 {
background: green;
color: white;
padding: 10px;
margin-bottom: 0;
}
input {
margin-bottom: 1em;
}
.section {
margin-bottom: 2em;
background: #f0f0f0;
padding: 10px;
}
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" version="XHTML+RDFa 1.0">
<head>
<title>Weather checker</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.11/angular.min.js"></script>
<script src="script.js"></script>
<link type="text/css" rel="stylesheet" href="style.css" media="all" />
</head>
<body>
<div class="container" ng-app="weatherApp">
<div ng-controller="MyWeatherController">
<h2>Current weather in {{city}}</h2>
<div class="section current">
<form name="weather-form">
<label for="city">City, State / Zip code</label>
<input
type="text"
ng-model="city"
ng-model-options="{updateOn: 'submit'}">
<br>
<label for="units">Units</label>
<input type="radio" ng-model="units" value="metric"> Metric
<input type="radio" ng-model="units" value="imperial"> Imperial<br>
<button ng-click="updateData()">Update</button>
<h3>{{data.name}}</h3>
<p>{{description}}</p>
<p>Temperature: {{main.temp}}</p>
<p>Wind speed: {{wind.speed}}</p>
</form>
</div>
</div>
</div>
</body>
</html>
I removed the ng-model-options="{updateOn: 'submit'} from your html and it's working fine :)
(function(angular) {
'use strict';
var myApp = angular.module('weatherApp', [])
.controller('MyWeatherController', ['$scope', '$http', '$log', 'weather', function($scope, $http, $log, weather) {
$scope.city = 'Cincinnati';
$scope.units = 'imperial';
$scope.updateData = function() {
weather.updateData($scope, $http, $log);
};
// Initial run to fetch weather data
$scope.updateData();
}])
// Set up a service factory to fetch current and forecast data
.factory('weather', ['$http', function($http) {
var services = {};
services.updateData = function(scope, http, log) {
this.updateCurrent(scope, http, log);
}
// Get current data
services.updateCurrent = function(scope, http, log) {
// Fetch current weather data from api
var url = 'http://api.openweathermap.org/data/2.5/weather';
http.jsonp(url, {params: {
q: scope.city,
units: scope.units,
callback: 'JSON_CALLBACK'
}})
.success(function(data, status, headers, config) {
scope.main = data.main;
scope.wind = data.wind;
scope.description = data.weather[0].description;
})
.error(function(data, status, headers, config) {
log.error('Could not retrieve data from '+url);
});
};
return services;
}]);
} (window.angular));
body {
width: 50%;
margin: 2em auto;
}
h2 {
background: green;
color: white;
padding: 10px;
margin-bottom: 0;
}
input {
margin-bottom: 1em;
}
.section {
margin-bottom: 2em;
background: #f0f0f0;
padding: 10px;
}
<!DOCTYPE html>
<html>
<head>
<title>Weather checker</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.11/angular.min.js"></script>
<script src="script.js"></script>
<link type="text/css" rel="stylesheet" href="style.css" media="all" />
</head>
<body>
<div class="container" ng-app="weatherApp">
<div ng-controller="MyWeatherController">
<h2>Current weather in {{city}}</h2>
<div class="section current">
<form name="weather-form">
<label for="city">City, State / Zip code</label>
<input
type="text"
ng-model="city">
<br>
<label for="units">Units</label>
<input type="radio" ng-model="units" value="metric"> Metric
<input type="radio" ng-model="units" value="imperial"> Imperial<br>
<button ng-click="updateData()">Update</button>
<h3>{{data.name}}</h3>
<p>{{description}}</p>
<p>Temperature: {{main.temp}}</p>
<p>Wind speed: {{wind.speed}}</p>
</form>
</div>
</div>
</div>
</body>
</html>
You have two ways (well, probably many more) you could go here.
You could create a promise and return the data that comes back from the http call in the promise, to be resolved in the controller. Check out the 2nd code block on the documentation for $q here to see how to do this.
I would suggest, however, that instead, in your service you create a public property to hold the data. You can then access it from your controller. Due to Angular's data binding, when the server response eventually comes back and the data gets stored in the service, the controller will automatically "see" the updated value.
(function(angular) {
'use strict';
var myApp = angular.module('weatherApp', [])
.controller('MyWeatherController', ['$scope', '$http', '$log', 'weather', function($scope, $http, $log, weather) {
//here you expose the service to your scope. From here you can
//get at all your data in the view by using weather.result
$scope.weather = weather;
$scope.city = 'Cincinnati';
$scope.units = 'imperial';
$scope.updateData = function() {
weather.updateData($scope, $http, $log);
};
// Initial run to fetch weather data
$scope.updateData();
}])
// Set up a service factory to fetch current and forecast data
.factory('weather', ['$http', function($http) {
var services = {};
//make the server response data part of the service's public API
services.details = {
someDetail: "",
someOtherThing: []
}
services.updateData = function(scope, http, log) {
this.updateCurrent(scope, http, log);
}
// Get current data
services.updateCurrent = function(scope, http, log) {
// Fetch current weather data from api
var url = 'http://api.openweathermap.org/data/2.5/weather';
http.jsonp(url, {params: {
q: scope.city,
units: scope.units,
callback: 'JSON_CALLBACK'
}})
.success(function(data, status, headers, config) {
//here we assign the data to the service's result property.
services.details.someDetail = data.someDetail;
services.details.someOtherThing = data.someOtherThing;
})
.error(function(data, status, headers, config) {
log.error('Could not retrieve data from '+url);
});
};
return services;
}]);
} (window.angular));
<p>Some detail:{{weather.details.someDetail}}</p>
<p>Some other thing: {{weather.details.someOTherThing}}</p>
I'm trying to add a controller in a new html content that will be added dynamically to an existing dom, but my scope is undefined. What is the best way of doing it? I'm new in Angular.
Sorry, here is my code:
var angularScript = document.createElement('script');
angularScript.setAttribute('type','text/javascript');
angularScript.setAttribute('src','https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js');
document.head.appendChild(angularScript);
jQuery('body').append("<section id='custFA'><div id='getTable' data-ng-app='custom' data-ng-controller='customController' style='overflow-y: auto !important;position:absolute; width: 300px; height: 200px; top:100px; left: 200px;'><button id='runCust' data-ng-click='codeRun()' style='top: 57px; left: 120px;'>Run</button></div></section>");
I'm inserting module and controller scripts as well, and the code in it:
Module:
setTimeout(function angularDefined(){
if(angular){
window.app = angular.module("custom",[]);
console.log("angular");
}
else{
setTimeout(angularDefined,1000);
}
},1000);
controller:
function appDefined(){
if(window.app){
window.defined=true;
console.log("appDefined");
app.controller('customController', ['$scope', function($scope) {
$scope.codeRun=function(){
console.log("check");
}
}]);
}
else{
setTimeout(appDefined,1000);
}
};
appDefined();
Thanks
You'll need to create a controller first..per the docs:
var myApp = angular.module('myApp',[]);
myApp.controller('GreetingController', ['$scope', function($scope) {
$scope.greeting = 'Hola!';
}]);
In your html: Let your view know which controller to use. Inside of that div you will have access to any variables on $scope
<div ng-controller="GreetingController">
{{ greeting }}
</div>
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..!!