ng-click : pass data selectedItem between pages angularjs - javascript

So, I was able to select Items of my list, but the aim is to pass the data of the selected list in another /route when I click on it. I would need a bit of help because I don't really know how to proceed please. If you know punker examples do not hesitate to tell me :)
Bellow is my optionSuggestionController
app.controller('optionSuggestionController', ['$scope', '$http', function($scope, $http) {
$http.get('suggestions.json')
.then(function(res){
$scope.suggestions = res.data;
});
$scope.setMaster = function(suggestion) {
$scope.selected = suggestion;
}
$scope.isSelected = function(suggestion) {
return $scope.selected === suggestion;
}
}])
Bellow is my list of data
<ul class="list-holder">
<li ng-repeat="suggestion in suggestions" ng-class="{active : isSelected(suggestion)}">
<a ng-click="setMaster(suggestion)">{{suggestion.fromto}}</a>
</li>
</ul>
Bellow is my suggestions.json
[{ "fromto": "Dublin to London", "img": "http://placekitten.com/100/100" },
{ "fromto": "Dublin to Paris", "img": "http://placekitten.com/100/100" },
{ "fromto": "Dublin to Mexico", "img": "http://placekitten.com/100/100" }]

I think you can use the provider '$rootScope'.
$rootScope.selected = suggestion;
You can access this data in an other controller.
Hope it helps.

I have two suggestions:
You can use the provider '$rootScope'.
$rootScope.selected = suggestion;
Or get param via url by provider '$route'.
var suggestion = $route.current.params.suggestion;

You can use Service or Factory to share your data between controllers, I create a Factory with your codes and call it on a control to use.
app.controller('optionSuggestionController', function ($scope, $filter, $timeout, $timeout, $http, testFactory) {
testFactory.get(function (resp) {
console.log(resp);
$scope.suggestions = resp;
});
});
app.factory('testFactory', function ($http) {
var databaseFactory = {};
databaseFactory.get = function (callback) {
return $http.get('suggestions.json').then(function (response) {
databaseFactory.returnedData = response.data;
callback(databaseFactory.returnedData);
});
}
return databaseFactory;
});

Related

select JSON object based on ui-router url

EDIT: Better phrasing of the question. I am basically looking at how to use the variable stored in $scope.item (grabbed from URL using $stateParams) to access the related object in the products JSON array.
Alright so I have used a combination of ui-router and ng-ref so that when you click a product on the "#/shop/" page it creates a URL "#/shop/productname" that when navigated to opens a blank div on the page that is meant to contain details about the product mentioned in the URL.
The issue I am having, and I'm sure there is something simple I am overlooking, is how to get the corresponding data based on the name in the URL? So that I can display product name/price etc that is stored in a JSON object?
Any help would help a ton! It's very possible I am going about this all wrong so please refer me in the right direction if you feel I could choose a better path.
HTML:
shop.html URL: #/shop
...
<a ng-repeat="item in businesses | filter:{cat: cat} | filter:query"
ng-class="{active: item.selected}"
ng-href="#/shop/{{item.link}}"
ng-click="selectedItem(item)">
...
</a>
<div ui-view></div>
...
product.html URL: #/shop/productName
<h1>item.name</h1>
<h2>item.price</h2>
App.js
angular.module('app', [
'ngAnimate',
'ui.router'
])
.config(function ($stateProvider, $urlRouterProvider){
$urlRouterProvider.otherwise('/shop');
$stateProvider
.state('shop',{
url: '/shop',
templateUrl: 'templates/shop.html',
controller: 'starWarsCtrl'
})
.state('shop.item',{
url: '/:item',
templateUrl: 'templates/three-quarter-page.html',
controller: function($scope, $stateParams){
$scope.item = $stateParams.item;
}
})
;
})
.controller('appCtrl', function ($scope) {
$scope.products = [
{
"name": "Product 1",
"index":1,
"link":"product1",
"price":"TBD",
}
];
$scope.selectItem = function (selectedItem){
_($scope.products).each(function (item){
item.selected = false;
if (selectedItem === item){
selectedItem.selected = true;
}
})
};
}) /*End Controller*/
});
This will get the selected item for you, assuming you match by the name.
$scope.selectedItem = _.where($scope.products, {name: $scope.item});
I think, if I were you I would use angular service to share data between controllers
and this service will handle the data for me so when I change the product it will return the item object
angular.module('app').factory('productsService', function () {
self = this;
self.products = [{
"name": "Product 1",
"index":1,
"link":"product1",
"price":"TBD",
}];
this.findByLink = function(link){
// loop through your data
// returns what found or null
}
return {
products : this.products
findById : this.findById
}
});
and inject this service in each controller
.controller('appCtrl', function ($scope, productsService) {
$scope.products = productsService.products;
..........
and to anther one
.controller('productCtrl', function ($scope, productsService, $stateParams) {
$scope.item = productsService.findById($stateParams.link);
..........

Can I get Angular variable of one controller in other (variable by $http)

I am new to Angularjs and studied a lot. But I stuck at a point. Google doesn't help me. I have a controller and I have data in $scope.results
app.controller('manage_categories', function($scope, $http, $filter, $window) {
$scope.results = [];
$http({
url: base_url + 'employee/fetchData?table=results',
method: "POST",
}).success(function(data) {
$scope.results = data;
});
})
now i want to access the same in other without any other $http call. I have done with another call but i don't want this . because i need this in many other controllers.something like this
app.controller('manage_users', function($scope, $http, $filter, $window,results) {
$scope.results = results;
//~ $http({
//~ url: base_url + 'employee/fetchData?table=results',
//~ method: "POST",
//~ }).success(function(data) {
//~ $scope.results = data;
//~ });
})
or any other method. Thanks.
update
I tried this
var myApp = angular.module('myApp',[]);
myApp.factory('results', function() {
return {
name : [{id:21,name:'this is test'}]
};
});
app.controller('manage_users', function($scope, $http, $filter, $window,results) {
$scope.results = results;
})
This is working fine . But not working with $http call .
var myApp = angular.module('myApp',[]);
myApp.factory('results', function($scope,$http) {
$scope.results=[];
$http({
url: base_url + 'employee/fetchData?table=results',
method: "POST",
}).success(function(data) {
$scope.results = data;
});
return {
name : results
};
});
update 2
after answers i write it like
var canapp = angular.module('canApp', ["ngRoute", "angularFileUpload"]);
canapp.service('ResultsFactory', ['$http', function($http) {
// http call here
var url=base_url + 'employee/fetchData?table=results';
$http.post(url,data).success(function(data){
this.results = data;
});
}])
call like this
canapp.controller('get_candidates', function($scope, $http, $filter, $timeout, $window, ResultsFactory) {
$scope.check=ResultsFactory.results;
});
but it is not setting the value in template
Use $broadcast to share the data between controllers. Your code will look like this
app.controller('manage_categories', function($scope, $http, $filter, $window, $rootScope) {
$scope.results = [];
$http({
url: base_url + 'employee/fetchData?table=results',
method: "POST",
}).success(function(data) {
$scope.results = data;
$rootScope.$broadcast("results",data);
});
});
app.controller('otherCtrlr', function($scope, $rootScope) {
$rootScope.$on("results", function(event, data){
$scope.results = data;
});
});
But using a service call in the controller is not a best approach. Create a factory and create a method to call your service.
From controller you need to call this method. But to avoid two service calls, you definitely need to use broadcast/emit(depending on data transfer is from parent or child)
There are various possible way of communicating between two controllers. If you just Google share data between controllers angularjs, you may found various links:
Using Services to Share Data Between Controllers
Sharing Data Between Controllers
Share data between AngularJS controllers
Passing data between controllers in Angular JS?
So, in short, possible ways are:
Using Angular Factories (recommended)
Using $rootScope (not recommended)
Using top most controller's scope as root scope
You can do this:
app.factory('ResultsFactory', resultsFactory);
resultsFactory.$inject = ['$http'];
function resultsFactory = function(){
var self = {};
var results = null;
self.getResults = function(){
if(!results){
$http.post(url,data).success(function(data){
results = data;
});
}else{
return results;
}
}
return self;
}
Only the first time that you call to ResultsFactory.getResults() this executes the $http call.
Here's a small fiddle explaining how to share data between controllers.
https://jsfiddle.net/frishi/zxnLwz6d/10/
(Check the browser console to see that both controllers can access data via the service.)
Basically the premise of a service is that it is a singleton that can be used by all the controllers registered on your module.
You want to make that $http call in a service:
.service('myService', ['$http', function($http) {
this.getData = function(){
// Simple GET request example:
return $http({
method: 'GET',
url: 'https://api.github.com/users/mralexgray/repos' // example API
}).then(function successCallback(response) {
return response;
}, function errorCallback(response) {
// return error message
});
}
}])
In your controller:
.controller('Controller2',['$scope','myService',function ($scope,myService) {
$scope.foo = myService.getData();
//resolve the promise:
$scope.foo.then(function(data){
console.log(data);
})
}
])
It is strongly recommended to use separated services as frishi pointed out. This sample is in single file and module just to make it readeable. Following implementation stores the promise and actual request is only made on the initial call to getFoo. The rest will get the response from the in memory promise.
'use strict';
angular.module('foo', [])
.factory('FooResource', function SessionResource($http) {
var fooPromise;
return {
getFoo: function getFoo() {
if(!fooPromise) {
fooPromise = $http.post('employee/fetchData?table=results');
}
return fooPromise;
}
};
})
.controller('FooController', function($scope, FooResource) {
FooResource.getFoo().then(function getFooSuccess(data) {
$scope.results = data;
});
});
I use this angular code with ionic framework
may be its help you..
my factory is..
angular.module('starter.services', [])
.factory('Chats', function() {
// Might use a resource here that returns a JSON array
// Some fake testing data
var chats = [{
id: 0,
name: 'Ben Sparrow',
lastText: 'You on your way?',
face: 'img/ben.png'
}, {
id: 1,
name: 'Max Lynx',
lastText: 'Hey, it\'s me',
face: 'img/max.png'
}, {
id: 2,
name: 'Adam Bradleyson',
lastText: 'I should buy a boat',
face: 'img/adam.jpg'
}, {
id: 3,
name: 'Perry Governor',
lastText: 'Look at my mukluks!',
face: 'img/perry.png'
}, {
id: 4,
name: 'Mike Harrington',
lastText: 'This is wicked good ice cream.',
face: 'img/mike.png'
}];
return {
all: function() {
return chats;
},
remove: function(chat) {
chats.splice(chats.indexOf(chat), 1);
},
get: function(chatId) {
for (var i = 0; i < chats.length; i++) {
if (chats[i].id === parseInt(chatId)) {
return chats[i];
}
}
return null;
}
};
});
and i use this factory in many controllers
.controller('ChatsCtrl', function($scope, Chats) {
$scope.chats = Chats.all();
$scope.remove = function(chat) {
Chats.remove(chat);
};
})
.controller('ChatDetailCtrl', function($scope, $stateParams, Chats) {
$scope.chat = Chats.get($stateParams.chatId);
})
in this code factory hit http:// request only one time and i use response on two controllers.
Hope its help you.

Call function or pass data to another controller AngularJS

I already have seem other topics with this kind of issue, but no one could help me... So here is my issue:
I have a navbar with a button for search, this buttons makes and get request from a webservice and returns a json object which must be apply to fill an table list. The problem is, my button and my table are in separated controllers, and it does work like I expected.
var app = angular.module('clientRest', []).controller('lista', ['$scope', 'loadLista', function($scope, loadLista) {
$scope.contatos = loadLista.getContatos();
}]).controller('pesquisa', ['$scope', '$http', 'loadLista', function($scope, $http, loadLista) {
$scope.listar = function() {
$http.get("http://localhost/wsRest/index.php/contato").success(function(response) {
loadLista.setContatos(response);
});
};
}]).service('loadLista', function() {
var contatos = [];
return {
getContatos: function() {
return contatos;
},
setContatos: function(c) {
contatos = c;
}
};
});
My code...
When I call listar() from pesquisa controller I need to send received data to $scope.contatos from lista controller to make my ng-repeat work, everything with a single click.
How can I do it?
Thanks everyone
Better to use a service to share data between two controllers / modules as this might be the best approach. You can refer the code segment given below to understand the concept.
angular.module('app.A', [])
.service('ServiceA', function() {
this.getValue = function() {
return this.myValue;
};
this.setValue = function(newValue) {
this.myValue = newValue;
}
});
angular.module('app.B', ['app.A'])
.service('ServiceB', function(ServiceA) {
this.getValue = function() {
return ServiceA.getValue();
};
this.setValue = function() {
ServiceA.setValue('New value');
}
});
In order to trigger the data receipt event, you may use
Broadcast / emit messages - with #broadcast / #emit
An angular promise with a call back
Controller initiation function to reload the previously read information from a service
.controller('MyController', function($scope, ServiceA) {
$scope.init = function() {
$scope.myValue = ServiceA.getValue();
};
// Call the function to initialize during Controller instantiation
$scope.init();
});
Use $rootScope.$emit to emit a change event when setting the variable and use $on to get the value in the lista controller. I used customListAr here just to demostrate a button click. Does this help?
var app = angular.module('clientRest', [])
.controller('lista', ['$scope', 'loadLista', '$rootScope',
function($scope, loadLista, $rootScope) {
console.log(loadLista);
$scope.contatos = loadLista.getContatos();
$rootScope.$on('change', function() {
$scope.contatos = loadLista.getContatos();
});
}
])
.controller('pesquisa', ['$scope', '$http', 'loadLista',
function($scope, $http, loadLista) {
$scope.listar = function() {
$http.get("http://localhost/wsRest/index.php/contato").success(function(response) {
loadLista.setContatos(response);
});
};
$scope.customListAr = function() {
loadLista.setContatos(["item 1" , "item 2", "item 3"]);
}
}
])
.service('loadLista', ['$rootScope',
function($rootScope) {
var contatos = [];
return {
getContatos: function() {
return contatos;
},
setContatos: function(c) {
contatos = c;
$rootScope.$emit('change');
}
};
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="clientRest">
<div ng-controller="lista">
<ul>
<li ng-repeat="a in contatos">{{a}}</li>
</ul>
</div>
<div ng-controller="pesquisa">
<button ng-click="customListAr()">Click Me</button>
</div>
</div>
Your problem is that when you do $scope.contatos = loadLista.getContatos(); you are setting a static value, and angular is unable to effectively create a watcher for that object because your setContatos method is creating a new object each time. To get around this, have the controller's scope hold a reference to the parent object and then it will automatically have a watcher on that object.
var app = angular.module('clientRest', [])
.controller('lista', ['$scope', 'loadLista', function($scope, loadLista) {
$scope.contatos = loadLista.contatos;
}])
.controller('pesquisa', ['$scope', '$http', 'loadLista', function($scope, $http, loadLista) {
$scope.listar = function() {
$http.get("http://localhost/wsRest/index.php/contato"
).success(function (response) {
loadLista.contatos.data = response;
});
};
}])
.service('loadLista', function() {
var lista = {
contatos: {},
};
return lista;
});
// view:
<ul>
<li ng-repeat="contato in contatos.data">
{{ contato }}
</li>
</ul>

Angular js display name based on selected item and url path

I am starting out on the angular seed. I have a json file that displays items like the below.
{
"id":"1",
"name":"Spain",
"abbrev":"esp"
}
When I click on a country in the list I want to the display the details such as the name for this item.
I have this working as shown below.
/* app.js */
'use strict';
// Declare app level module which depends on views, and components
angular.module('myApp', ['ngRoute','myApp.controllers','myApp.services'])
.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/', {
templateUrl: 'templates/view1.html',
controller: 'CountryCtrl'
});
}])
.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/:name', {
templateUrl: 'templates/view2.html',
controller: 'CountryCtrl'
});
}])
.config(['$routeProvider', function($routeProvider) {
$routeProvider.otherwise({redirectTo: '/'});
}]);
/* services.js */
angular.module('myApp.services', [])
.factory('Countries', ['$http', function($http) {
var Countries = {};
Countries.name = '';
Countries.listCountries = function () {
return $http.get('../api/countries');
},
Countries.ChangeName = function (value) {
Countries.name = value;
}
return Countries;
}]);
/* controllers.js */
angular.module('myApp.controllers', [])
.controller('CountryCtrl', ['$scope', 'Countries', '$location', function($scope, Countries,$location) {
listCountries();
function listCountries() {Countries.listCountries()
.success(function (data, status, headers, config) {
$scope.countries = data.countries;
})
.error(function(data, status, headers, config) {
$scope.status = 'Unable to load data: ' + error.message;
});
}
$scope.name = Countries.name;
$scope.changeView = function(countryName,indx){
$location.path(countryName);
$scope.name = Countries.ChangeName(countryName);
}
}]);
/* templates/view1.html */
<ul>
<li ng-repeat="country in countries">
<div ng-click="changeView(country.name,$index)">{{country.name}}</div>
</li>
</ul>
/* templates/view2.html */
{{name}}
What I can't get to work is that if I go to http://www.example.com/app/#/ then navigate to spain in the list then I get taken to http://www.example.com/app/#/esp and {{name}} gets outputted as esp.
However if I navigate straight to http://www.example.com/app/#/esp without first clicking on spain in the list I get no value in my $scope.name
How can I achieve this?
I want the name to also be set based on the location path if it is available.
I know that $location.$$path will get me /esp however I don't really think this is the best idea to use this incase the url builds out to something bigger eg http://www.example.com/app/#/esp/events
can I some how access the index or id of the item so that I can then access the data like
{{countries[0].name}}
where 0 is id of esp - 1.
What is the best approach?
Mate, there are a couple of issues with your app.
Your service retains "state" although is only used to retrieve information
You're using the same controller to 2 different views (bad practice)
$scope.status = 'Unable to load data: ' + error.message; --> Error is not defined
There are a couple of js errors too, like strayed commas and stuff
Anyways, here's a revised version of your code. Fiddle
// Instantiate your main module
var myApp = angular.module('myApp', ['ngRoute']);
// Router config
myApp.config(['$routeProvider',
function($routeProvider) {
$routeProvider
.when('/', {
templateUrl: 'templates/view1.html',
controller: 'CountryListCtrl'
})
.when('/:id', {
templateUrl: 'templates/view2.html',
controller: 'CountryCtrl'
})
}
]);
// Your Factory. Now returns a promise of the data.
myApp.factory('Countries', ['$q',
function($q) {
var countriesList = [];
// perform the ajax call (this is a mock)
var getCountriesList = function() {
// Mock return json
var contriesListMock = [{
"id": "0",
"name": "Portugal",
"abbrev": "pt"
}, {
"id": "1",
"name": "Spain",
"abbrev": "esp"
}, {
"id": "2",
"name": "Andora",
"abbrev": "an"
}];
var deferred = $q.defer();
if (countriesList.length == 0) {
setTimeout(function() {
deferred.resolve(contriesListMock, 200, '');
countriesList = contriesListMock;
}, 1000);
} else {
deferred.resolve(countriesList, 200, '');
}
return deferred.promise;
}
var getCountry = function(id) {
var deferred = $q.defer();
if (countriesList.length == 0) {
getCountriesList().then(
function() {
deferred.resolve(countriesList[id], 200, '');
},
function() {
deferred.reject('failed to load countries', 400, '');
}
);
} else {
deferred.resolve(countriesList[id], 200, '');
}
return deferred.promise;
}
return {
getList: getCountriesList,
getCountry: getCountry
};
}
]);
//Controller of home page (pretty straightforward)
myApp.controller('CountryListCtrl', ['$scope', 'Countries',
function($scope, Countries) {
$scope.title = 'Countries List';
$scope.countries = [];
$scope.status = '';
Countries.getList().then(
function(data, status, headers) { //success
$scope.countries = data;
},
function(data, status, headers) { //error
$scope.status = 'Unable to load data:';
}
);
}
]);
// controller of Country page
// Notice how we use $routeParams to grab the "id" of our country from the URL
// And use our service to look for the actual country by its ID.
myApp.controller('CountryCtrl', ['$scope', '$routeParams', 'Countries',
function($scope, $routeParams, Countries) {
$scope.country = {
id: '',
name: '',
abbrev: ''
};
var id = $routeParams.id;
Countries.getCountry(id).then(
function(data, status, hd) {
console.log(data);
$scope.country = data;
},
function(data, status, hd) {
console.log(data);
}
);
}
]);
In your "CountryCtrl", if you include $routeParams and use $routeParams.tlaname, you will have access to the tlaname. You can then use that to initialize your data.

How to add filter inside my app

I am having trouble using the Angular filter in my app.
I have something like
app.controller('test', function($scope, $filter){
myService.get('api/v1/products/?id=1').success(function(data) {
$scope.products = data;
$filter('testFilter', function() {
return function(products, item) {
//codes...
}
})
})
}
html
<div ng-repeat="product in products | testFilter:5 "> {{product.title}} </div>
However, I am getting testFilterProvider unknown error. Can someone help me out on this one? Thanks a lot!
To create a filter, you need to call filter() on the module...
app.filter('testFilter', function() {
return function(products, item) {
//codes...
};
});
And if you want use that filter in your controller, you can call the $filter service to retrieve it...
app.controller('test', function($scope, $filter){
myService.get('api/v1/products/?id=1').success(function(data) {
$scope.products = data;
var filteredProducts = $filter('testFilter')($scope.products, 5);
});
}

Categories

Resources