Where to persist data used by many controllers in AngularJS? [duplicate] - angularjs

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

Passing Object from One Controller to Another AngularJS

I need to pass an object from one controller to another and have used this solution but it is not working.
Here the code:
angular.module("customerApp", [])
.controller('MainCtrl', function ($scope, myService, $http, $location) {
var vm = this;
vm.pinFormCheck = function () {
vm.count++;
if (vm.pinForm.$valid && vm.details.PIN === vm.pin && vm.count <= 2) {
location.href = "http://localhost:51701/Home/MainMenu";
$scope.obj = {
'cid': 'vm.details.CID',
'name': 'vm.details.Name',
'pin': 'vm.details.PIN',
'bal': 'vm.details.Bal',
'status': 'vm.details.cardStatus'
};
console.log(vm.details.Bal);//the correct balance get displayed in console
} else {
vm.failPin = true;
}
};
})
.controller('CheckCtrl', function ($scope, myService) {
$scope.data = myService.getObj();
})
.factory('myService', function () {
var obj = null;
return {
getObj: function () {
return obj;
},
setObj: function (value) {
obj = value;
}
}
});
Here is the view from which the first object is passed:
<body ng-app="customerApp">
<div ng-controller="MainCtrl as vm">
<form name="vm.pinForm">
<input type="password" ng-model="vm.pin" ng-required="true" />
<p><button ng-disabled="vm.count >=3" ng-click="vm.pinFormCheck();" ng-init="vm.count=0">Proceed</button></p>
</form>
...
Here' the second view where I need the object
<html ng-app="customerApp">
<body ng-controller="CheckCtrl">
<div>
<h1>your balance is {{data.bal}}</h1>
....
The balance from vm.details.Bal from the first view must appear in data.bal in the second view, but nothing is appearing.
You can just save vm.details in some factory.
And then get it in CheckCtrl from this factory.
Factories in AngularJS implement singleton pattern. So saved data will be kept in until your app exists.
You tried to do next thing myService.getObj(); But you didn't save anything to the service.
Inject myService to the MainCtrl and then save details into it.

How to link Laravel controller function with Angular View

I am working on a laravel web application , recently i embedded angularjs for searching data from database. But for now i just used an array to search.In my AngularJs Module i point to search function as $scope.url = 'Students#search'; but this is not working for me. I want to know that how to tell AngularJS $scope.url to point to this search function in my Controller so that user can search data easily.
I have search function in Students Controller:
public function search(){
$data = file_get_contents("php://input");
$objData = json_decode($data);
// Static array for this demo
$values = array('php', 'web', 'angularjs', 'js');
// Check if the keywords are in our array
if(in_array($objData->data, $values)) {
echo 'I have found what you\'re looking for!';
}
else {
echo 'Sorry, no match!';
}
}
MyApp.js File :
function SearchCtrl($scope, $http) {
$scope.url = 'Students#search'; // The url of our search
// The function that will be executed on button click (ng-click="search()")
$scope.search = function() {
// Create the http post request
// the data holds the keywords
// The request is a JSON request.
$http.post($scope.url, { "data" : $scope.keywords}).
success(function(data, status) {
$scope.status = status;
$scope.data = data;
$scope.result = data; // Show result from server in our <pre></pre> element
})
.
error(function(data, status) {
$scope.data = data || "Request failed";
$scope.status = status;
});
};
}
Angular Search View:
<div ng-controller="SearchCtrl">
<form class="well form-search">
<label>Search:</label>
<input type="text" ng-model="keywords" class="input-medium search-query" placeholder="Keywords...">
<button type="submit" class="btn" ng-click="search()">Search</button>
<p class="help-block">Try for example: "php" or "angularjs" or "asdfg"</p>
</form>
<pre ng-model="result">
#{{result}}
</pre>
</div>
You may create a route first. For example-
Route::get("/search", ["as" => "studentSearch", "uses" => "Students#search"]);
then you can set it like
$scope.url = '{{ route ("studentSearch") }}';
Or if its not a blade template then you have to manually set the url. Like
$scope.url = '/search';

Use one service with 2 different controllers angularjs and be able to send the data to the third controller angularjs

<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

What to use instead of $rootScope? [duplicate]

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.

passing ng-show between two different controllers

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!

Resources