How to send data from one controller to another controller in angularjs - angularjs

Below is my playlist json data coming from playlist controller.
{
"id":18,
"file":{"url":"/uploads/playlist/file/18/01_-_MashAllah.mp3"},
"event_id":23,"created_at":"2015-11-11T10:33:52.000Z",
"updated_at":"2015-11-11T10:33:52.000Z",
"name":"01 - MashAllah.mp3"
},
{
"id":19,
"file":{"url":"/uploads/playlist/file/19/02_-_Laapata.mp3"},
"event_id":19,"created_at":"2015-11-11T10:50:01.000Z",
"updated_at":"2015-11-11T10:50:01.000Z",
"name":"02 - Laapata.mp3"
}
Now i want to bind id and name to a playerController am i doing something like this
<div ng-controller="playlistsController">
<div ng-repeat="playlist in playlists">
<div ng-controller='PlayerController'>
<input type=hidden ng-model="ID" ng-init="ID=playlist.id">
<input type=hidden ng-model="Name" ng-init="Name=playlist.name">
</div>
</div>
</div>
and in controller
.controller('PlayerController',['$scope',function($scope) {
console.log($scope.ID);
console.log($scope.name);
}]);
but the console is showing undefined.
i don't know where i am going wrong as i am new to angular.

METHOD 1:
The best way to share data between controllers is to use services. Declare a service with getters and setters and inject into both the controllers as follows:
service:
app.service('shareData', function() {
return {
setData : setData,
getData : getData,
shared_data : {}
}
function setData(data) {
this.shared_data = data
}
function getData() {
return this.shared_data
}
})
With your service defined, now inject into both the controllers and use the parent controller (in your case) to set the data as follows:
app.controller('playlistsController', function(shareData) {
//your data retrieval code here
shareData.setData(data);
})
And finally in your child controller, get the data:
app.controller('PlayerController', function(shareData) {
$scope.data = shareData.getData();
})
METHOD 2:
Since, you have to communicate data from parent controller to child controller, you can use $broadcast as follows:
parent controller:
//retrieve data
$scope.$broadcast('setData', data);
And receive the data in child controller:
$scope.$on('setData', function(event, args) {
$scope.data = args;
})

First controller code is executed, then angular starts proceed html this controller is attached to. So just move your variable initialization to controller:
$scope.Name = $scope.playlist.name;
$scope.ID = $scope.playlist.id;
or just use original variables (if you dont need copy of them)
<input type=hidden ng-model="ID=playlist.id">
<input type=hidden ng-model="Name=playlist.name">
or you may leave it as is - it works disregarding that you don't see values in log.

You should use $parent:
JSFiddle
HTML:
<div ng-controller="playlistsController">
<div ng-repeat="playlist in playlists">
<div ng-controller='PlayerController'>
<input type="text" ng-model="$parent.playlist.id">
<input type="text" ng-model="$parent.playlist.name">
</div>
</div>
</div>
JS:
app.controller('PlayerController', function ($scope, $sce) {
console.log($scope.$parent.playlists);
});

Related

AngularJS - How to pass data from View (HTML) to Controller (JS)

I am really new to AngularJS. I want to pass some object from View (HTML) to my controller (JS).
Actually my Client will send me data in HTML and I have to take that data and process that data in my controller and then display the processed output on screen. He will be using some back-end technology called ServiceNow - https://www.servicenow.com/ .
All the solutions I saw had some event like click event or change event, but in my case this has to be done on page load.
I m using Input type hidden for passing the data to the controller, seems like it's not working.
So is there any other way I can do this ?
Here's the code I am trying to use
<div ng-controller="progressController" >
<input type="hidden" value="ABCD" ng-model="testingmodel.testing">
</div>
app.controller('progressController', function($scope) {
console.log($scope.testingmodel.testing);
});
It says undefined when I console.log my variable in Controller.
You're doing console.log(...) too early. At this time your controller doesn't have any information from the view.
The second problem is that you're binding the view to a variable in controller and not the other way around. Your $scope.testingmodel.testing is undefined and it will obviously the value in the view to undefined.
Solution
Use ng-init to initialize the model and the controller's hook $postLink to get the value after everything has been initialized.
Like this
<div ng-controller="progressController" >
<input type="hidden" ng-model="testingmodel.testing" ng-init="testingmodel.testing = 'ABCD'">
</div>
app.controller('progressController', function($scope) {
var $ctrl = this;
$ctrl.$postLink = function() {
console.log($scope.testingmodel.testing);
};
});
Edit: extra tip
I don't recomment using $scope for storing data since it makes the migration to newer angular more difficult.
Use controller instead.
Something like this:
<div ng-controller="progressController as $ctrl" >
<input type="hidden" ng-model="$ctrl.testingmodel.testing" ng-init="$ctrl.testingmodel.testing = 'ABCD'">
</div>
app.controller('progressController', function() {
var $ctrl = this;
$ctrl.$postLink = function() {
console.log($ctrl.testingmodel.testing);
};
});
You should use the ng-change or $watch
<div ng-controller="progressController" >
<input type="hidden" value="ABCD" ng-model="testingmodel.testing" ng-change="change()">
</div>
app.controller('progressController', function($scope) {
$scope.change = function(){
console.log($scope.testingmodel.testing);
}
});
Or:
app.controller('progressController', function($scope) {
$scope.$watch('testingmodel.testing', function(newValue, olValue){
console.log(newValue);
}
});
If you use ng-change, the function is only called if the user changes the value in UI.
If you use $watch anyway, the function is called.
You can't use value attribute for set or get value of any control, angularJS use ngModel for set or get values.
Here You should try like this way
app.controller('progressController', function($scope) {
//from here you can set value of your input
$scope.setValue = function(){
$scope.testingmodel = {}
$scope.testingmodel.testing = 'ABCD';
}
//From here you can get you value
$scope.getValue = function(){
console.log($scope.testingmodel.testing);
}
});
if you want to bind from html side then you should try like below
<input type="text" ng-model="testingmodel.testing">
<input type="hidden" ng-model="testingmodel.testing">

Angular Nested Controller Data access

I don't know how to access the data from a nested ( child ) controller.
<form ng-controller="TestController as test" ng-submit="submit()">
<h5>Employee name :</h5>
<div ng-controller="mainCtrl" class="row-fluid">
<form class="row-fluid">
<div class="container-fluid">
<input type="text" ng-model="name" typeahead="name for name in names | filter:$viewValue" />
</div>
</form>
</div>
<h5>Comment : </h5>
<textarea ng-model="test.test_content"></textarea>
<input type="submit" id="submit" value="Submit" />
</form>
As you can see i have 2 controllers.The main one is a form , the second one is an input box that allows the user to search the name in a list using typeahead.
I want to be able to acces the content of ng-model="name" in my child controller (mainctrl) in my TestController.
I've tried to access it directly with $scope.name but it doesn't work.
I've also tried test.name as the ng-model and it didn't work either.
I'm sending the data of my TestController to my server and would like to send the data ( name ) from my mainCtrl aswell, directly from TestController. So that when my user click submit it send both the name + the test_content in $http.post request.
Anyone know how to do that ?
Thanks
I've found this but it didn't really help.. https://fdietz.github.io/recipes-with-angular-js/controllers/sharing-models-between-nested-controllers.html
edit:
my search controller
.controller("mainCtrl", function ($scope, $http) {
$scope.selected = '';
$http.get('/feedbacks/search.json').
then(function(response) {
$scope.succes = " ok "
$scope.names = response.data;
// this callback will be called asynchronously
// when the response is available
}, function(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
$scope.succes = " error"
});
});
my form controller :
angular.module('FeedbackTool')
.controller('TestController',['$scope', '$http', function($scope,$http) {
$http.get('/feedbacks.json').
then(function(response) {
$scope.succes = " ok "
$scope.list = response.data;
// this callback will be called asynchronously
// when the response is available
}, function(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
$scope.succes = " error"
});
$scope.submit = function() {
$http.post('/feedbacks.json', { data:this.test }).
then(function(response) {
$scope.succes = 'sent';
// this callback will be called asynchronously
// when the response is available
}, function(response) {
// called asynchronously if an error occurs
// or server returns response with an error status.
$scope.succes = 'fail';
});
};
}]);
The parent scope is accessible from within the child scope, but the child scope is not accessible from the parent. Typically the way to deal with this is to assign values from the child scope to properties already defined in the parent. In your case I think you just need to use test.name as the ng-model expression.

Not able to load $http.get - JSON data in ui tabset child tabs

I tried to load a dropdown with the response got from http post. But its failing to load on child tabs.
When i click next button from tab1. I make a post call and get a JSON back. Using the returned data i want to load a dropdown in my second tab.
I already raised a query on tabset and it worked fine. Now I modified the plunker little bit. I did the same way mentioned in the below link. But i'm missing something when i try to do the samething with $http.get
Tabset $rootScope scope not updating
app.js
angular.module('plunker', ['ui.bootstrap'])
.service('Common', function() {
this.tabData = {};
})
.controller('SampleController', function($scope, $http, Common) {
$scope.submitTab1 = function() {
$http.get("post.json", {
// Some logic
}).success(function(data) {
Common.tabData = data;
$scope.steps.step2 = true;
});
}
})
.controller("SampleTab2Controller", function($scope, Common) {
$scope.userList = Common.tabData;
});
Html
<tabset ng-init="steps={step1:true, step2:false}">
<tab heading="Step 1" active="steps.step1">
<div data-ng-controller="SampleController">
<form data-ng-submit="submitTab1()">
<label>Some Operations ...</label>
<br>
<br>
<label>Click next to retrieve json from server ...</label>
<button type="submit">Click Next</button>
</form>
</div>
</tab>
<tab heading="Step 2" active="steps.step2">
<div data-ng-controller="SampleTab2Controller">
<form name="step2">
<p>load the json list from Tab1 controller </p>
<select ng-model="selectedUser" ng-options="user.title for user in userList">
<option value="">--- select ---</option>
</select>
</form>
</div>
</tab>
</tabset>
Post.json
[
{
"id": 1,
"title": "Arnold"
},
{
"id": 2,
"title": "stallone"
}
]
Plunker Code http://plnkr.co/edit/EZC1d6tDDZlpWZUHY6os?p=preview
Your issue has nothing to do with loading from http, but it has to do with properly copying reference of objects.
When you do $scope.userList = Common.tabData; the reference of tabData is copied to userList, and then when the tabData is updated using Common.tabData = data now tabData in the service points to a different reference and $scope.userList keeps pointing to the old one. So instead of getting the reference of tabData and copying it to the userList, set up the service object itself on the scope.
In your controller change $scope.userList = Common.tabData to $scope.userList = Common :-
.controller("SampleTab2Controller", function($scope, Common) {
$scope.userList = Common;
});
and in the view iterate upon userList.tabData
<select ng-model="selectedUser" ng-options="user.title for user in userList.tabData">
Plnkr
If I modified your code this way it works
1) changed tabData to be an array
2) Used angular.copy instead of asignning
.service('Common', function() {
this.tabData = []; ==> Changed this to array
})
$http.get("post.json", {
// Some logic
}).success(function(data) {
angular.copy(data,Common.tabData); ==> Used angular copy so it copies the array
$scope.steps.step2 = true;
});
Updated Plnkr
main issue in your code is controller get executed first and then Common.tabData is loaded.so can do like this:
angular.module('plunker', ['ui.bootstrap'])
.service('Common', function() {
this.tabData = {};
})
.controller('SampleController', function($scope,$http, Common) {
$scope.submitTab1 = function() {
$http.get("post.json", {
// Some logic
}).success(function(data) {
Common.tabData = data;
$scope.steps.step2 = true;
});
}
})
.controller("SampleTab2Controller", function($scope, Common) {
$scope.userList = Common;
});
and html code according to this is:
<div data-ng-controller="SampleTab2Controller">
<form name="step2">
<p>load the json list from Tab1 controller </p>
<select ng-model="selectedUser" ng-options="user.title for user in userList.tabData">
<option value="">--- select ---</option>
</select>
</form>
</div>

Angularjs change view without a click

I am stil new to Angular, but trying, very hard, to get my head round it.
Basically, I just want to move from one view, to another one function is complete. Here is the code:
App.controller('clientLogin', function ($scope, $http, $route) {
$scope.clientLoginBt = function () {
var sun = $('#ClientUsername').val();
var spa = $('#ClientPassword').val()
$http({url: "/sources/",
headers: {"X-Appery-Database-Id": dbid},
params: {where: '{"$and" : [{"username": "' + sun + '"}, {"password" : "' + spa + '"}]}'}})
.success(function (data) {
console.log(data.length);
$scope.clientLogggedin = data;
if (data.length > 0) {
$route.clientLogggedin();
} else {
}
})
.error(function (status) {
console.log('data on fail: ' + status);
});
}
});
Above, if the data comes back with more than one row, the user log is correct, and I just want to change view!
I have tried $location, did not work, and as Angular is really simple to use, in the amount of coding, I cannot see any info on it, other than if you click, it starts a controller.
Here is the HTML:
<div class="row" ng-controller="clientLogin">
<div class="large-12 medium-12">
<input type="text" id="ClientUsername" placeholder="Enter Username" />
<input type="password" id="ClientPassword" placeholder="Enter Password" />
<button ng-click="clientLoginBt()">Login</button>
</div>
</div>
The page I am looking to jump to, within the is called clientLoggedIn.html.
I have also added it to the config, thinking i could access it with $route :
App.config(function ($routeProvider) {
$routeProvider
.when('/',
{
templateUrl: 'views/home.html'
})
.when('/userLogin', {
templateUrl : 'views/userLogin.html',
controller: 'userLoginController'
})
.when('/clientLogin', {
templateUrl : 'views/clientLogin.html',
controller: 'clientLoginController'
})
.when('/clientLoggedIn', {
templateUrl : 'views/clientLoggedIn.html',
controller: 'clientLoggedInController'
})
.otherwise({
redirectTo : '/'
}
);
});
Any ideas on what I am doing wrong please ?
Thanks in advance.
Using path method of $location should do the trick. Since you want to get to clientLoggedIn.html, you would need to use the matching route (/clientLoggedIn):
$location.path("/clientLoggedIn");
Be sure that $location service is injected into your App Controller. This is the line you should probably replace with what I have above:
$route.clientLogggedin();
It is just a matter of checking an indicator whether the $http call was successful or not. If you are not willing to add a routing for clientLoggedIn.html. You can do something like below, just to enable the logged in page:
<div class="row" ng-controller="clientLogin">
<div class="large-12 medium-12" ng-hide="sucessfulLogin">
<input type="text" id="ClientUsername" placeholder="Enter Username" />
<input type="password" id="ClientPassword" placeholder="Enter Password"/>
<button ng-click="clientLoginBt()">Login</button>
</div>
<ng-include src="'views/clientLoggedIn.html'" ng-show="sucessfulLogin">
</ng-include>
<!-- or just include the DOM element here if you do not
want a separate html altogether-->
</div>
and in the REST call:
if (data.length > 0) {
//Assuming the flag in pre-initialized to false in controller
$scope.sucessfulLogin = true;
} else {
}
Also note, using ng-include directive you can still use a separate controller in clientLoggedIn.html if you are willing to. Just have to use ng-controller in the first element inside clientLoggedIn.html.

AngularJS - Passing data between pages

I am an AngularJS starter. I am trying to send data from :
Page A : Van Listing page
to
Page B: Van Update page.
When user click the update link for a van, I am invoking a controller and retrieving the van details in the controller. But, I cannot assign the van details to the Page B ( Van Update Page) using the same controller... Error "Cannot set property 'vanNumber' of undefined"
*** Page A: Van List ****
<form name="listVanForm" >
<table>
<tr> <td ng-controller="VanUpdateCtrl">update</td> </tr>
</table>
</form>
*** Page B: Van Update ****
<div class="container">
<h2>Edit Van </h2>
<form name="updateVanForm" novalidate="novalidate" class="form-horizontal" ng-submit="updateCard(formData)">
<div class="control-group">
<label class="control-label" >Van Number:</label>
<div class="controls">
<input type="text" id="vanNumber" ng-model="formData.vanNumber" placeholder=""/>
</div>
</div>
</form>
</div>
*** VanUpdateCtrl **
app.controller('VanUpdateCtrl', ['$scope', 'VanUpdateFactory', '$location',
function ($scope, VanUpdateFactory, $location) {
//callback for ng-init 'populateDD':
$scope.prePopulateForm = function (cardNoParam m) {
alert('cardNo = '+cardNoParam);
$scope.formData.cardNumber=cardNoParam;}
}
So, $scope.formData.cardNumber OR $scope.formData in the destination page is not recognised.
You need to create a service to be able to share data between controllers.
app.factory('myService', function() {
var savedData = {}
function set(data) {
savedData = data;
}
function get() {
return savedData;
}
return {
set: set,
get: get
}
});
In your controller A:
myService.set(yourSharedData);
In your controller B:
$scope.desiredLocation = myService.get();
Remember to inject myService in the controllers by passing it as a parameter.
What you should do is create a service to share data between controllers.
Nice tutorial https://www.youtube.com/watch?v=HXpHV5gWgyk
If you only need to share data between views/scopes/controllers, the easiest way is to store it in $rootScope. However, if you need a shared function, it is better to define a service to do that.
app.factory('persistObject', function () {
var persistObject = [];
function set(objectName, data) {
persistObject[objectName] = data;
}
function get(objectName) {
return persistObject[objectName];
}
return {
set: set,
get: get
}
});
Fill it with data like this
persistObject.set('objectName', data);
Get the object data like this
persistObject.get('objectName');

Resources