I'm new to angular and I'm wondering how I can share a variable between controllers in angular. I'm using the following scripts -
In Main.js:
function MainCntl($scope) {
---code
}
function SearchCtrl($scope, $http) {
$scope.url = 'http://10.0.0.13:9000/processAdHoc';
$scope.errorM = "No results";
$scope.search = function() {
$http.post($scope.url, { "data" : $scope.keywords}).
success(function(data, status) {
$scope.status = status;
$scope.data = data;
$scope.result = data;
alert('yes');
})
.
error(function(data, status) {
$scope.data = data || "Request failed";
$scope.status = status;
alert('no');
$scope.result = "failed";
});
};
}
In Index.html
<body ng-controller="MainCntl" >
---code
<div ng-controller="SearchCtrl">
<form class="well form-search">
<div class="ui-widget">
<label for="tags"></label>
<a ng-click="search()"><input type="image" src="../../images/search1.png" class="searchbox_submit" /></a>
<input ng-model="keywords" placeholder="Shadow Search" id="tags" class="input-medium search-query rounded" />
</div>
</form>
</div>
---code
<p ng-model="result">
{{result}}
</p>
</body>
Everything works well with the ajax I'm sending data and receiving a response, my question is as follows:
In the SearchCtrl function I have a variable called $scope.result that is later referred to in Index.html. If I insert the html code that contains that variable into the SearchCtrl controller it works fine but if it is in the MainCtrl controller it does not work. How can I share this variable between the controllers.
Thanks ahead
Use a service and inject it to both controllers and refer your scope vars to the services variable.
Example:
angular.module("yourAppName", []).factory("myService", function(){
return {sharedObject: {data: null } }
});
function MainCtrl($scope, myService) {
$scope.myVar = myService.sharedObject;
}
function SearchCtrl($scope, $http, myService) {
$scope.myVar = myService.sharedObject;
}
In your template do:
{{myVar.data}}
See an example Uses Angular v1.1.5
The reason you put it in an inner object is to preserve your references, if you keep it without a "sharedObject", and change that object, your binding will be pointing to the old reference and wouldn't show anything in the template.
Related
<div data-ng-app="myApp" data-ng-controller="ProjectHighLigthsController">
<div ng-form="userForm">
<img alt="" data-ng-click="addAnswers($event)" data-ng-show="isAdmin" src="/SaveBttn.png"
style="width: 100px; height: 50px;" />
<img alt="" onclick="Close()" src="/Close.png" />
Division:<select class="dropdown" name="Division" data-ng-model='selectedDivision' data-ng-options='item.DivisionName for item in Divisions'></select>
<span style="color: Red; font-weight: lighter;" ng-show="userForm.Division.$error.empty">Division is not selected</span>
Year<select class="dropdown" data-ng-model='selectedYear' name="Year" data-ng-options='item.Year for item in Years'></select>
<span style="color: Red; font-weight: lighter;" ng-show="userForm.Year.$error.empty">Year is not selected</span></div>
</div>
The items in the dropdown are being pulled from sharepoint list and the code is all under one controller. On addAnswers Event the data is being stored in the list again in the same controller.
I would like to create a service and have different controllers to bind data to the dropdown list and a different controller to save the data. And below is the code I have written
var myApp = angular.module('myApp', []);
myApp.config(function ($httpProvider) {
//Enable cross domain calls
$httpProvider.defaults.useXDomain = true;
delete $httpProvider.defaults.headers.common['X-Requested-With'];
});
myApp.service('getItensforDropdownService', ['$http', function ($http) {
var list = function (username) {
return $http({
method: 'GET',
url: username,
withCredentials: true,
dataType: 'json',
headers: { "Accept": "application/json; odata=verbose" }
});
}
return {
Items: list
};
}]);
And the Controllers are :
myApp.controller('DivisionCtrl', ['$scope', 'getItensforDropdownService',
function ($scope, getItensforDropdownService) {
getItensforDropdownService.Items("/Division")
.success(function (data, status, headers, config) {
data.d.results.unshift({ DivisionName: '---Select---' });
// do magic stuff with the result
// (which is in the data param)
$scope.Items = data.d.results;
$scope.selectedOption = $scope.Items[0];
})
.error(function (data, status, headers, config) {
$scope.getCallJSONResult = "data not retrieved";
})
}]);
However, I dont understand how do I pass the values of the selected dropdowns in the new controller on ng-click for Addanswers($event)
Please let me know how do I get this to work.
If you want to share data between views/controllers, you can use the getter/setter approach in a service. Below is a simple example that will hopefully be helpful and make sense.
When you click the button in the snippet below, Controller1 stores your selection (in this example, letters) in a service. You could then have any other controller retrieve these values from the service, and/or update the values. An example of how another controller can call these stored values is shown in Controller2 code below.
angular.module('ionicApp', ['ionic'])
.controller('Controller1', function($scope, divisionService) {
$scope.firstList = ["a", "b", "c"];
$scope.secondList= ["f", "g", "h"];
$scope.first = "a";
$scope.second = "f";
$scope.set = function(first,second) {
divisionService.setLetters(first,second);
alert("First letter = " + first + " and Second letter =" + second + ". These have been updated in divisionService and can be called/updated by any other controller");
}
})
.controller('Controller2', function($scope, divisionService) {
$scope.get = function() {
//get 'stored' letters from divisionService
var selectedLetters = divisionService.getLetters();
$scope.firstLetter = selectedLetters.firstLetter;
$scope.secondLetter = selectedLetters.secondLetter;
}
})
.factory('divisionService', function($http) {
var selectedLetters = {}
return {
setLetters: function(firstLetter,secondLetter) {
selectedLetters.firstLetter = firstLetter;
selectedLetters.secondLetter = secondLetter;
},
getLetters: function() {
return selectedLetters;
}
}
})
<html ng-app="ionicApp">
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
<title>Ionic Template</title>
<link href="http://code.ionicframework.com/1.0.0-beta.2/css/ionic.css" rel="stylesheet">
<script src="http://code.ionicframework.com/1.0.0-beta.2/js/ionic.bundle.js">
</script>
</head>
<body ng-controller="Controller1">
</ion-content>
<div>
<select ng-model="first" ng-options="letter for letter in firstList "></select>
<select ng-model="second" ng-options="letter for letter in secondList "></select>
<button class="button button-small button-positive" ng-click="set(first,second)">Store these options in a service</button>
</div>
</ion-content>
</body>
</html>
At this point in your code, you are in fact returning a promise object rather than the results of the $http call, as you might expect.
return {
Items: list
};
(list also represents an un-executed function, you never access the return value from it because you aren't referencing that function as list().. or you could define it as list = function(){ ... }()
your Items property is set to a promise of a response from a request - The solution below is how to do asynchronous external data correctly: use the function that deals with a successfully returned promise: .then(), and execute the GET request with myService.asyncFuncNameAsdf(), and use the then function on the returned promise to work with the data returned.
service
app.factory('myService', function($http) {
return {
asyncFuncNameAsdf: function() {
return $http.get('test.json'); //1. this returns promise
}
};
});
controller
app.controller('MainCtrl', ['myService', '$scope', function( myService,$scope) {
myService.asyncFuncNameAsdf().then(function(d) { //2. so you can use .then()
console.log(d);
$scope.data = d; // update {{data}} when AJAX complete
});
}]);
second and third controllers communicating using a service
app.controller('SecondCtrl', ['myService', '$scope', '$timeout',function( myService, $scope, $timeout){ function( myService, $scope, $timeout){
$scope.shared_property = myService.shared_property || "about to change";
$timeout(function(){
myService.shared_property = "Hello services";
}, 3000); // 3 seconds later controller 2 and 3 will update
}]).controller('ThirdCtrl', ['myService', '$scope', '$timeout', function( myService, $scope, $timeout){
$scope.shared_property = myService.shared_property || "Not updated yet"; // this will change from "not set yet" to the property after the second controller changes it
}]);
further reading
I'm new to angular and I'm wondering how I can share a variable between controllers in angular. I'm using the following scripts -
In Main.js:
function MainCntl($scope) {
---code
}
function SearchCtrl($scope, $http) {
$scope.url = 'http://10.0.0.13:9000/processAdHoc';
$scope.errorM = "No results";
$scope.search = function() {
$http.post($scope.url, { "data" : $scope.keywords}).
success(function(data, status) {
$scope.status = status;
$scope.data = data;
$scope.result = data;
alert('yes');
})
.
error(function(data, status) {
$scope.data = data || "Request failed";
$scope.status = status;
alert('no');
$scope.result = "failed";
});
};
}
In Index.html
<body ng-controller="MainCntl" >
---code
<div ng-controller="SearchCtrl">
<form class="well form-search">
<div class="ui-widget">
<label for="tags"></label>
<a ng-click="search()"><input type="image" src="../../images/search1.png" class="searchbox_submit" /></a>
<input ng-model="keywords" placeholder="Shadow Search" id="tags" class="input-medium search-query rounded" />
</div>
</form>
</div>
---code
<p ng-model="result">
{{result}}
</p>
</body>
Everything works well with the ajax I'm sending data and receiving a response, my question is as follows:
In the SearchCtrl function I have a variable called $scope.result that is later referred to in Index.html. If I insert the html code that contains that variable into the SearchCtrl controller it works fine but if it is in the MainCtrl controller it does not work. How can I share this variable between the controllers.
Thanks ahead
Use a service and inject it to both controllers and refer your scope vars to the services variable.
Example:
angular.module("yourAppName", []).factory("myService", function(){
return {sharedObject: {data: null } }
});
function MainCtrl($scope, myService) {
$scope.myVar = myService.sharedObject;
}
function SearchCtrl($scope, $http, myService) {
$scope.myVar = myService.sharedObject;
}
In your template do:
{{myVar.data}}
See an example Uses Angular v1.1.5
The reason you put it in an inner object is to preserve your references, if you keep it without a "sharedObject", and change that object, your binding will be pointing to the old reference and wouldn't show anything in the template.
// I have written java code to fetch data from mongo-db. What i need to do is on tick of checkbox button i have to display those data in drop-down menu using angular-js and bootstrap. Nothing is happening after doing these code.
.html page
<div ng-controller="release">
<div class="col-md-2 col-centered col-fixed">
<label for="cloneRelease" translate="release.form.cloneRelease">CloneRelease</label>
</div>
<div>
<input type="checkbox" ng-model="ticked">
<div class="dropdown-menu" ng-repeat="release in releaseName" ng-show="ticked">{{release.name}}</div>
</div>
</div>
controller.js
releaseApp.controller('release', function($scope, $location, $http, ReleaseNameService){
$scope.releaseName = [];
init();
function init(){
ReleaseNameService.getReleaseName().then(function(data){
$scope.releaseName = data;});
console.log('inside controller: '+$scope.releaseName);
}
});
service.js
releaseApp.factory('ReleaseNameService', function($http){
var releaseName = [];
var factory = {};
factory.getReleaseName = function(){
return $http.get('release/fetchAllReleaseDetails').then(function(response){
releaseName = response.data;
console.log('inside service method'+ releaseName);
return releaseName;
});
};factory;
});
It is simple, u need to bind checkbox with ng-model:
<input type="checkbox" ng-model="ticked">
If its ticked $scope.ticked return true, else return false. If true show data, if false hide it (with ng-show)
Here is an example in jsFiddle without css ofc.
http://jsfiddle.net/RLQhh/2282/
UPDATE:
recreateing case with service.
service.js
app.factory('dataService', function ($http) {
var dataObject= {
async: function () {
var promise = $http.get('data/').then(function (response) {
return response;
});
return promise;
}
};
return dataObject;
})
controller.js
$scope.dataTest = [];
$scope.ticketed = false;
var getData = function(){
dataService.async().then(function (d) {
$scope.dataTest = d.data;
});
}
getData();
html
<input type="checkbox" ng-model="ticketed">
<div ng-show="ticketed" ng-repeat="dat in dataTest">
{{dat.name}}
</div>
...this is tested case so it should work with yours
You can make a REST call to fetch the data from your java function and store it in scope.Then you can use ng-repeat to display data in dropdown.
Here is a very good article on how to do it.
http://www.infragistics.com/community/blogs/dhananjay_kumar/archive/2015/06/29/how-to-work-with-the-bootstrap-dropdown-in-angularjs.aspx
I have a button which falls into Controller B and two block of HTML code which kind of falls under controller A...............and button falls into one block of HTML code
Example:
<div ng-controller="A">
<div ng-show="now">
<div>
<Button ng-controller="B"></Button>
</div>
</div>
<div ng-show="later">
</div>
</div>
On one button click I show up now block and later on button click of B controller I kind of hide now block and display later block.
How do I achieve this functionality?? I am not able to pass ng-show varibales between two different controller files......what should I use???
Hope this helps...!
angular.module('app', [])
.controller('A', function($scope) {
console.log('A');
$scope.state = {
now: true
};
$scope.showLater = function() {
$scope.state.later = true;
};
})
.controller('B', function($scope) {
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-controller="A" ng-app="app">
<div ng-show="state.now">
<div>
<button ng-controller="B" ng-click="showLater()">Show Later</button>
</div>
</div>
<div ng-show="state.later">LATER
</div>
<p> <pre ng-bind="state | json"></pre>
</p>
</div>
You could use a simple service that stores the state.
Example:
angular.module('mymodule').service('ActiveService', function() {
var service = {};
var status = false;
service.getStatus = function() {
return status;
}
service.toggle = function() {
status = !status;
}
return service;
})
And in your controller:
angular.module('mymodule').controller('SomeController', function(ActiveService) {
$scope.status = ActiveService.getStatus;
})
The Angularjs service is a singelton, so it will hold your values for you across different controllers, directives or pages.
Could also be used directly:
// Controller
$scope.service = ActiveService;
// Html
<div ng-show="service.getStatus()">
...
</div>
You can also achieve this by declaring the variable in $rootScope and watching it in controller A,
app.controller('A', function($scope, $rootScope) {
$rootScope.now = true;
$rootScope.later = false;
$rootScope.$watch("now", function() {
$scope.now = $rootScope.now;
$scope.later = !$rootScope.now;
})
});
In Controller B, you just change the value of now based on previous value like this on ng-click,
app.controller('B', function($scope, $rootScope) {
$scope.testBtn = function() {
$rootScope.now = !$rootScope.now;
}
});
I have implemented a button within different divs(now and later) in a plunker,
http://embed.plnkr.co/xtegii1vCqTxHO7sUNBU/preview
Hope this helps!
So I keep getting this ReferenceError: $http is not defined, even though I have included $http in the controller, which seems to be the most common cause of this error message. I've tried also passing $http into the function itself, but that doesn't solve it.
I feel like I am missing something SUPER obvious, so any help would be much appreciated, thank you!
I've included the entire script, just for clarity's sake. You can see the post request towards the end of the script, inside the finaliseDay function.
Thanks!
Here is the error:
ReferenceError: $http is not defined
at l.$scope.finaliseDay (http://localhost:8888/goalzy.js:69:12)
at ib.functionCall (https://ajax.googleapis.com/ajax/libs/angularjs/1.3.13/angular.min.js:198:303)
at Dc.(anonymous function).compile.d.on.f (https://ajax.googleapis.com/ajax/libs/angularjs/1.3.13/angular.min.js:214:485)
at l.$get.l.$eval (https://ajax.googleapis.com/ajax/libs/angularjs/1.3.13/angular.min.js:125:305)
at l.$get.l.$apply (https://ajax.googleapis.com/ajax/libs/angularjs/1.3.13/angular.min.js:126:6)
at HTMLAnchorElement.<anonymous> (https://ajax.googleapis.com/ajax/libs/angularjs/1.3.13/angular.min.js:215:36)
at HTMLAnchorElement.c (https://ajax.googleapis.com/ajax/libs/angularjs/1.3.13/angular.min.js:32:389)angular.js:11607 (anonymous function)angular.js:8557 $getangular.js:14502 $get.l.$applyangular.js:21440 (anonymous function)angular.js:3014 c
Here is the HTML first
<!doctype html>
<html ng-app="goalzy">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.13/angular.min.js"></script>
<script src="goalzy.js"></script>
</head>
<body>
<div class="container">
<div class="well">
<h2>Goalzy</h2>
Dev TODO
<ul>
<li>Hook up the API to persist data</li>
</ul>
<div ng-controller="TodoController">
<span>{{remaining()}} of {{todos.length}} remaining today</span>
<span>You're at {{percentComplete()}}% completion</span>
[ finalise day ]
<ul class="unstyled">
<li ng-repeat="todo in todos">
<input type="checkbox" ng-model="todo.done">
<span class="done-{{todo.done}}">{{todo.text}}</span>
</li>
</ul>
<form ng-submit="addTodo()">
<input type="text" ng-model="todoText" size="30"
placeholder="add new todo here">
<input class="btn-primary" type="submit" value="add">
</form>
<hr>
<div class="historial" ng-repeat="h in historicalDailyPercentages">
<ul>
<li>Date: {{h.date}}</li>
<li>Percentage of Daily Tasks Completed: {{h.percent}}%</li>
<li><div>Tweet it!</div></li>
</ul>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
And here is the JS:
//Goalzy.js
angular.module('goalzy', [])
.config(['$httpProvider', function($httpProvider) {
$httpProvider.defaults.headers.post['Content-Type'] = 'application/json; charset=utf-8';
});
.controller('TodoController', ['$scope','$http', function($scope, $http) {
$scope.todos = [];
$scope.historicalDailyPercentages = [];
$scope.addTodo = function() {
if ($scope.todoText != "") {
if ($scope.todos.length < 3) {
$scope.todos.push({text:$scope.todoText, done:false});
$scope.todoText = '';
//Save to DB
}
else {
alert("You can only have 3 todos per day!");
$scope.todoText = '';
}
} else {
alert("you must write something");
}
};
$scope.remaining = function() {
var count = 0;
angular.forEach($scope.todos, function(todo) {
count += todo.done ? 0 : 1;
});
return count;
};
$scope.percentComplete = function() {
var countCompleted = 0;
angular.forEach($scope.todos, function(todo) {
countCompleted += todo.done ? 1 : 0; //Simply calculates how many tasks have been completed
console.log(countCompleted);
});
var totalCount = $scope.todos.length;
var percentComplete = countCompleted / totalCount * 100;
return percentComplete;
}
$scope.finaliseDay = function(percentComplete) {
alert("You're finalising this day with a percentage of: " + percentComplete);
var today = new Date();
var alreadyPresent = $scope.historicalDailyPercentages.some(function (item) {
return item.date.getFullYear() === today.getFullYear() &&
item.date.getMonth() === today.getMonth() &&
item.date.getDate() === today.getDate();
});
//Confirm that nothing has alreayd been posted for today
if (!alreadyPresent) {
$scope.historicalDailyPercentages.push({
percent: percentComplete,
date: today
});
// Simple POST request example (passing data) :
$http.post('/api/postDailyPercentage.php', {msg:'hello word!'}).
success(function(data, status, headers, config) {
// this callback will be called asynchronously
// when the response is available
console.log("data" + data);
}).
error(function(data, status, headers, config) {
// called asynchronously if an error occurs
// or server returns response with an error status.
console.log("data" + data);
});
}
else {
alert("You're all set for today - see you tomorrow!");
}
console.log($scope.historicalDailyPercentages);
}
}]);
Provider won't be available inside controller with suffix 'Provider', you can do access them by provider name only here it would be $http only, also remove ;
after config initialization
$httpProvider setting should be done inside the angular config phase
CODE
angular.module('goalzy', [])
.config(['$httpProvider', function($httpProvider) {
$httpProvider.defaults.headers.post['Content-Type'] = 'application/json; charset=utf-8';
}]);
.controller('TodoController', ['$scope', '$http', function($scope, $http) {
//controller code here
}]);
Note: For sure you should remove $httpProvider.defaults.headers.post['Content-Type'] = 'application/json; charset=utf-8'; line from controller
Working Plunkr
You don't have to use "$httpProvider" in controller, use $http instead.
e.g.
$http.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8';
As best practice, do not configure provider ($http) in controller. Do it in config section. as below
var app = angular.module('goalzy', []);
app.config(function ($httpProvider) {
$httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8';
});
app.controller('TodoController', ['$scope','$http', function($scope, $http) {
$scope.title="scope title";
//$httpProvider.defaults.headers.post['Content-Type'] = 'application/x-www-form-urlencoded;charset=utf-8';
}]);
see working plunk at http://run.plnkr.co/plunks/4mY4izqc48P8wVQFumZ8/ with your html.