I try to do my first angularjs application, but i have a problem. I have 2 controllers (and i would like to keep 2): the first to list items, the second to edit or create an item.
When I save an item, or create a new item, i can't edit another or create another, after to do one action the form can't load or save... The problem seems to be this line :
$scope.editPlace = {};
But I don't understand why...
DEMO :
http://jsfiddle.net/cxL7qmke/
HTML:
<div ng-app="mapApp">
<div ng-controller="EditPlaceCtrl">
<form name="editPlaceForm">
<fieldset>
<label for="title">Title:</label>
<input id="title" type="text" ng-model="editPlace.title">
<input type="hidden" ng-model="editPlace.id" />
<button type="submit" ng-click="savePlace()">Save</button>
</fieldset>
</form>
</div>
<section ng-controller="PlaceCtrl">
<ul>
<li ng-repeat="place in places">
<label>{{place.title}} edit</label>
</li>
</ul>
</section>
</div>
JS :
var mapApp = angular.module('mapApp', []);
mapApp.controller('PlaceCtrl', function ($scope, $rootScope, placeService) {
$scope.places = placeService.getAll();
$scope.edit = function (id) {
$rootScope.editPlace = angular.copy(placeService.get(id));
}
});
mapApp.controller('EditPlaceCtrl', function ($scope, placeService) {
$scope.savePlace = function () {
placeService.save($scope.editPlace);
$scope.editPlace = {};
}
});
mapApp.service('placeService', function ($filter) {
var uid = 3;
var places = [
{ id: 1, title: 'Item1', lat: 43.123, lng: -89.123 },
{ id: 2, title: 'Item2', lat: 43.321, lng: -89.321 }
];
this.getAll = function () {
return places;
}
this.get = function (id) {
var place, i;
for (i in places) {
if (places[i].id === id) {
return places[i];
}
}
return false;
};
this.save = function (place) {
if (place.id == null) {
place.id = this.uid++;
places.push(place);
} else {
for (i in places) {
if (places[i].id == place.id) {
places[i] = place;
}
}
}
};
});
I've made few changes and seems to work for me please see here
http://jsfiddle.net/m9bevovy/
in your service I've added
this.newPlace = {};
this.setNew = function (id) {
this.newPlace = this.get(id);
};
and your controllers :
mapApp.controller('PlaceCtrl', function ($scope, $rootScope, placeService) {
$scope.places = placeService.getAll();
$scope.edit = function (id) {
placeService.setNew(id);
}
});
mapApp.controller('EditPlaceCtrl', function ($scope, placeService) {
$scope.placeService = placeService;
$scope.savePlace = function () {
placeService.save($scope.placeService.newPlace);
$scope.placeService.newPlace = {};
}
});
You are using both $scope and $rootScope to hold the reference to editPlace.
If you want to use the $rootScope, use this in your savePlace function:
$rootScope.editPlace = {};
Instead of:
$scope.editPlace = {};
Here`s the working fiddle
Related
I am trying to activate a checkbox from a controller that lives in another controller. For example, I have a card named information technology under a separate controller and when I click this I want it to route to another page that has a checkbox for information technology from another controller and I want it checked as it renders the page.
The application architecture is very lengthy so I wont include any code base here. But I would like to know an approach I can take.
This is the controller where I want the logic to live and to mark a text box as checked (which lives on another controller).
angular
.controller("mycontroller", mycontroller);
mycontroller.$inject = [
"$scope"
];
// getting the getData() data
$scope.getData = function (data, type) {
console.log("whats this data about in getData(data) ", data)
$scope.query = data.name;
if (data.checked == undefined) {
data.checked = true;
}
}
Below: Is the controller where the checkbox controller lives
angular
.controller('supplierIntelligenceCtrl', function ($scope, $q, FetchData, dataStore, SharedService,
$document, $window, $state, $rootScope, $timeout, DataCache,
$filter, $interval, $localStorage, $http) {
$scope.getData = function (data, type) {
console.log("whats this data about in getData(data) ", data)
$scope.query = data.name;
if (data.checked == undefined) {
data.checked = true;
}
}
$scope.apply = function (type) {
$scope.select = false;
$scope.bigres = 0;
$scope.mobFil = 3;
$scope.applyFilter(type);
}
$scope.disableApply = false;
$scope.disableApply2 = false;
$scope.applyFilter = function (type) {
console.log("this is type ", type)
if (type == 'industries') {
$scope.filters.industries = $scope.industries.filter(function (e) {
console.log("this is e ", e.checked)
return e.checked;
}).map(function (f) {
console.log(" this is f >>>> ",
f)
return f.id
})
$scope.filters.countries = [];
if ($scope.countries != undefined) {
$scope.countries = $scope.countries.map(function (e) {
e.checked = false;
return e;
})
}
$scope.filters.cities = [];
if ($scope.cities != undefined) {
$scope.cities = $scope.cities.map(function (e) {
e.checked = false;
return e;
})
}
$scope.start = 0;
if ($scope.filters.industries.length > 0) {
$scope.callBackend();
$scope.disableApply2 = true;
FetchData.fetchDNBCountriesByIndustries('industries=' + $scope.filters.industries + '&size=').then(function (res) {
$scope.disableApply2 = false;
$scope.countries = res.data;
$scope.countriesPage += 10
}, function () {
$scope.disableApply2 = false;
});
} else {
$scope.callBackend();
}
}
if (type == 'countries') {
$scope.filters.countries = $scope.countries.filter(function (e) {
return e.checked;
}).map(function (f) {
return f.id;
})
$scope.filters.cities = [];
if ($scope.cities != undefined) {
$scope.cities = $scope.cities.map(function (e) {
e.checked = false;
return e;
})
}
$scope.start = 0;
if ($scope.filters.countries.length > 0) {
$scope.callBackend();
$scope.disableApply2 = true;
FetchData.fetchDNBCitiesByIndustriesAndCountries('industries=' + $scope.filters.industries + '&countries=' + $scope.filters.countries + '&size=').then(function (res) {
$scope.disableApply2 = false;
$scope.cities = res.data;
}, function () {
$scope.disableApply2 = false;
})
} else {
$scope.callBackend();
}
}
if (type == 'cities') {
$scope.filters.cities = $scope.cities.filter(function (e) {
return e.checked;
}).map(function (f) {
return f.id
})
$scope.start = 0;
$scope.callBackend();
}
if (type == 'classifications') {
$scope.filters.classifications = $scope.classifications.filter(function (e) {
return e.checked;
}).map(function (f) {
return f.statusCode;
})
$scope.start = 0;
$scope.callBackend();
}
}
}
Here is the HTML where the checkbox lives:
<div ng-repeat="data in industries ">
<input id="{{data.id}}in" type="checkbox" aria-invalid="false"
ng-model="data.checked"
ng-change="getData(data,'industry')">
<label for="{{data.id}}in">{{data.name}}</label>
</div>
Maybe Im missing the point here and perhaps am overlooking something. Im new to angularjs and need to implement this capability to route a button/card to another page that checks a checkbox filter.
Please - any advise would be great . :)
Here is an example of controllers sharing an array via a shared service injected by the dependency injector. Check the checkbox in one controller and it shows in the other.
angular.module('app', []);
angular.module('app')
.factory('dataService', [function () {
return {
data: [
{ prop: '1', checked: false },
{ prop: '2', checked: false },
{ prop: '3', checked: false },
{ prop: '4', checked: false }
]
};
}]);
angular.module('app')
.controller('controller1', ['dataService', function (dataService) {
this.data = dataService.data;
}]);
angular.module('app')
.controller('controller2', ['dataService', function (dataService) {
this.data = dataService.data;
}]);
angular.module('app')
.controller('controller3', ['dataService', function (dataService) {
this.toggleAll = () => {
dataService.data.forEach(item => item.checked = !item.checked)
};
}]);
[ng-controller] { display: inline-block; margin-right: 30px; vertical-align: top; }
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.2/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="controller1 as ctrl">
<strong>Controller 1</strong>
<div ng-repeat="item in ctrl.data">
<label>Item {{item.prop}} <input type="checkbox" ng-model="item.checked"></label>
</div>
</div>
<div ng-controller="controller2 as ctrl">
<strong>Controller 2</strong>
<div ng-repeat="item in ctrl.data">
<label>Item {{item.prop}} <input type="checkbox" ng-model="item.checked"></label>
</div>
</div>
<div ng-controller="controller3 as ctrl">
<strong>Controller 3</strong>
<div>
<button ng-click="ctrl.toggleAll()">Toggle all</button>
</div>
</div>
</div>
Put industries as a property on a shared service that you inject into both of the controllers by the dependency injector. Then one controller can bind it to it's view and the other one can change the checked properties on them.
Since you are talking about redirection and then checking a check box, you can try either of below options
Send selection 'information technology' in query string to redirected page and check the check box
If you own a back end server then put the value in cookie and read it in your angular js app
Hope this helps.
I am trying to pass data through <select multiple> from HTML to my RESTful.
That data is an array of String. I don't know why when it comes to my backend it's empty.
This is my REST:
#PutMapping("/events")
#Timed
public ResponseEntity<Event> updateEvent(#RequestBody Event event, #ModelAttribute("attendeesToParse") ArrayList<String> attendeesToParse) throws URISyntaxException {
//Some code
}
This is my HTML:
<div class="form-group">
<label>Attendees</label>
<select class="form-control" multiple name="attendeesToParse" ng-model="vm.usernames"
ng-options="customUser as customUser.username for customUser in vm.customusers">
<option value=""></option>
</select>
</div>
I tried to fix this one for days, I googled it so much but I found no solutions. Please help me.
I can not change my HTML into a JSP due to my project's structure and business logic.
Why does it come empty? If I try to show some logs I see an empty array [].
UPDATE
My HTML form call:
<form name="editForm" role="form" novalidate ng-submit="vm.save()">
<!-- some code -->
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal" ng-click="vm.clear()">
<span class="glyphicon glyphicon-ban-circle"></span> <span data-translate="entity.action.cancel">Cancel</span>
</button>
<button type="submit" ng-disabled="editForm.$invalid || vm.isSaving" class="btn btn-primary">
<span class="glyphicon glyphicon-save"></span> <span data-translate="entity.action.save">Save</span>
</button>
</div>
</form>
My event-dialog-controller.js: (is the .js controller that works with form)
(function() {
'use strict';
angular
.module('businessRequestApp')
.controller('EventDialogController', EventDialogController);
EventDialogController.$inject = ['$timeout', '$scope', '$stateParams', '$uibModalInstance', '$q', 'entity', 'Event', 'Desk', 'CustomUser'];
function EventDialogController ($timeout, $scope, $stateParams, $uibModalInstance, $q, entity, Event, Desk, CustomUser) {
var vm = this;
vm.event = entity;
vm.clear = clear;
vm.datePickerOpenStatus = {};
vm.openCalendar = openCalendar;
vm.save = save;
vm.reftables = Desk.query({filter: 'event-is-null'});
$q.all([vm.event.$promise, vm.reftables.$promise]).then(function() {
if (!vm.event.refTable || !vm.event.refTable.id) {
return $q.reject();
}
return Desk.get({id : vm.event.refTable.id}).$promise;
}).then(function(refTable) {
vm.reftables.push(refTable);
});
vm.customusers = CustomUser.query();
$timeout(function (){
angular.element('.form-group:eq(1)>input').focus();
});
function clear () {
$uibModalInstance.dismiss('cancel');
}
function save () {
vm.isSaving = true;
if (vm.event.id !== null) {
Event.update(vm.event, onSaveSuccess, onSaveError);
} else {
Event.save(vm.event, onSaveSuccess, onSaveError);
}
}
function onSaveSuccess (result) {
$scope.$emit('businessRequestApp:eventUpdate', result);
$uibModalInstance.close(result);
vm.isSaving = false;
}
function onSaveError () {
vm.isSaving = false;
}
vm.datePickerOpenStatus.date = false;
function openCalendar (date) {
vm.datePickerOpenStatus[date] = true;
}
}
})();
My event-service.js:
(function() {
'use strict';
angular
.module('businessRequestApp')
.factory('Event', Event);
Event.$inject = ['$resource', 'DateUtils'];
function Event ($resource, DateUtils) {
var resourceUrl = 'api/events/:id';
return $resource(resourceUrl, {}, {
'query': { method: 'GET', isArray: true},
'get': {
method: 'GET',
transformResponse: function (data) {
if (data) {
data = angular.fromJson(data);
data.date = DateUtils.convertLocalDateFromServer(data.date);
}
return data;
}
},
'update': {
method: 'PUT',
transformRequest: function (data) {
var copy = angular.copy(data);
copy.date = DateUtils.convertLocalDateToServer(copy.date);
return angular.toJson(copy);
}
},
'save': {
method: 'POST',
transformRequest: function (data) {
var copy = angular.copy(data);
copy.date = DateUtils.convertLocalDateToServer(copy.date);
return angular.toJson(copy);
}
}
});
}
})();
My event.controller.js:
(function () {
'use strict';
angular
.module('businessRequestApp')
.controller('EventController', EventController);
EventController.$inject = ['Event', 'CustomUser', '$scope'];
function EventController(Event, CustomUser, $scope) {
var vm = this;
vm.events = [];
vm.customUsers = [];
vm.usernames = ["test1", "test2", "test3"];
$scope.allCustomUsers = [];
loadAll();
function loadAll() {
Event.query(function (result) {
vm.events = result;
vm.searchQuery = null;
});
CustomUser.query(function (result) {
vm.customUsers = result;
vm.searchQuery = null;
for (var i = 0; i < vm.customUsers.length; i++) {
$scope.allCustomUsers.push(vm.customUsers[i].username);
}
});
}
}
})();
If you're using angularJS, you can't data bind data with #ModelAttribute, because #ModelAttribute exists only with template engines such as JSP, and AngularJS is not a template engine within Spring. Try instead to use #RequestBody on String parameter, and then extract the data using Jackson.
One more issue, How exactly do you pass your values from front to back? I don't see any $http angularJS call, and no HTML form with POST method.
i am trying to save number of students at the time,i wrote the following code but i did not know where to go further. any more info or links to resources regarding this topic would be much appreciated
what i have done so far :
<div ng-controller="MainCtrl">
<fieldset data-ng-repeat="student in students">
<input type="text" ng-model="student.class" name="" placeholder="Class Name ">
<input type="text" ng-model="student.firstname" name="" placeholder="First Name ">
<input type="text" ng-model="student.lastname" name="" placeholder="Last Name ">
<button class="btn btn-danger" ng-show="$last" ng-click="removeStudent()">-</button>
</fieldset>
<button class="btn btn-primary" ng-click="addNewStudent()">New Student</button>
<button class="btn btn-primary" ng-click="save()">Save</button>
<button class="btn btn-warning" ng-click="cancel()">Cancel</button>
</div>
the controller is:
app.controller('MainCtrl', function($scope, $modalInstance, $students) {
$scope.students = [];
$scope.addNewStudent = function() {
$scope.students.push({
classname: "",
firstname: "",
lastname: ""
});
};
$scope.removeStudent = function() {
var lastItem = $scope.students.length - 1;
$scope.students.splice(lastItem);
};
$scope.save = function() {
$modalInstance.close($scope.students);
};
$scope.delete = function() {
$scope.students['deleted'] = 1;
$modalInstance.close($scope.students);
};
$scope.cancel = function() {
$modalInstance.dismiss('cancel');
};
});
in the view i can write the infos of students but when i click save button it only save the first student
modal instance:
$scope.openStudent = function (student) {
var modalInstance = $modal.open({
templateUrl: 'modalStudent.html',
controller: 'mainCTRL',
windowClass:'app-modal-window',
resolve: {
students: function () {
var students= {};
if (student !== undefined){
students['classname'] = student.classname;
students['firstname'] = student.firstname ;
students['lastname'] = student.lastname;
students['nachname'] = student.nachname;
}
console.log("studinfo",students);
return students;
}
}
});
modalInstance.result.then(function (students) {
if (students.deleted === undefined || students.deleted == 0) {
oStudent = { classname: students.classname,
firstname: students.firstname,
lastname: students.lastname,
delete_time:"0000-00-00 00:00:00"
};
saveStudent( $indexedDB,Student).then( function(id) {
$scope.buildMenu();
});
} else {
oStudent = { id: students.id,
delete_time:new Date().toISOString()
};
deleteStudent( $indexedDB, $scope, students.id).then( function(id) {
saveStudent( $indexedDB, Student, $scope.selectedUser.id ).then( function(id) {
$scope.buildMenu();
});
});
}
}, function () {
//console.log('Modal Student dismissed at: ' + new Date());
});
}
In case its a modal where you are passing the existing students objects, your controller code should be modified as:
Also you should use two separate views in this case for add and edit to avoid code cluttering. Because in case of addition students will be an array of objects and in case of edit it will be a single object where you cannot use ng-repeat as it wont work
app.controller('MainCtrl', function($scope, $modalInstance, students) {
//students variable contains information about the student to be edited, so your code should be something like this
if(students.classname !== undefined){
$scope.students = students;
}else{
$scope.students = [];
}
// rather than re-initializing each time modal gets opened you should retain value from students that you are passing
$scope.addNewStudent = function() {
$scope.students.push({
classname: "",
firstname: "",
lastname: ""
});
};
$scope.removeStudent = function() {
var lastItem = $scope.students.length - 1;
$scope.students.splice(lastItem);
};
$scope.save = function() {
$modalInstance.close($scope.students);
//make sure to save this when modal closes in the variable you are returning students from when modal is triggered
};
$scope.delete = function() {
$scope.info['deleted'] = 1;
$modalInstance.close($scope.students);
};
$scope.cancel = function() {
$modalInstance.dismiss('cancel');
};
});
I have two angularJS controllers that should be synchronized.
The first is a filter on a list, second displays the list. I have a service user by both controllers and that makes some async ajax-like calls.
My problem is that the filter filters before the list is initialized, so when the page loads for the first time I have unfiltered results. How to solve it?
Here is my JSFiddle
Here is the code:
var myApp = angular.module('myApp', []);
myApp.controller("infoCtrl", function ($scope, $timeout, person) {
person.get().then(function (response) {
// timeout to prevent '$digest already in progress' error
$timeout(function () {
$scope.people = response;
$scope.$apply();
})
});
});
myApp.controller("filterCtrl", function ($scope, person) {
$scope.$watch("maxAge", function (newValue) {
if (newValue) {
person.filterPeople(newValue);
}
});
});
myApp.service("person", function ($q, $timeout) {
var _me = this;
var AjaxGetPeople = function () {
return $timeout(function () {
var somedata = [{name: 'Marcel Sapin',age: 26},
{name: 'Anhel De Niro',age: 42},
{name: 'Johny Resset',age: 30}];
_me.people = somedata;
return somedata;
});
};
var filterPeople = function (maxAge, collection) {
if (!collection) collection = _me.people;
if (!collection) return;
angular.forEach(collection, function (p) {
p.visible = (p.age <= maxAge);
});
};
var get = function () {
if (_me.people) { // return from 'cache'
return $q.resolve(_me.people);
}
// if not 'cached', call 'ajax'
return AjaxGetPeople().then(function (response) {
// add visible property to people
filterPeople(100, response);
_me.people = response;
return response;
});
};
return {
'get': get,
'filterPeople': filterPeople
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="filterCtrl" ng-init="maxAge=30">People younger than
<input ng-model="maxAge" type="number" /> years:
</div>
<hr/>
<div ng-controller="infoCtrl">
<div ng-repeat="person in people" ng-show="person.visible">
{{person.name}}, age {{person.age}}
</div>
</div>
</div>
Anhel De Niro, age 42 should not be displayed when the page is loaded initially, because my filter's max age is 30...
Well, try initialize like this:
var myApp = angular.module('myApp', []);
myApp.controller("infoCtrl", function ($scope, $timeout, person) {
person.get(30).then(function (response) {
// timeout to prevent '$digest already in progress' error
$timeout(function () {
$scope.people = response;
$scope.$apply();
})
});
});
myApp.controller("filterCtrl", function ($scope, person) {
$scope.$watch("maxAge", function (newValue) {
if (newValue) {
person.filterPeople(newValue);
}
});
});
myApp.service("person", function ($q, $timeout) {
var _me = this;
var AjaxGetPeople = function () {
return $timeout(function () {
var somedata = [{name: 'Marcel Sapin',age: 26},
{name: 'Anhel De Niro',age: 42},
{name: 'Johny Resset',age: 30}];
_me.people = somedata;
return somedata;
});
};
var filterPeople = function (maxAge, collection) {
if (!collection) collection = _me.people;
if (!collection) return;
angular.forEach(collection, function (p) {
p.visible = (p.age <= maxAge);
});
};
var get = function (init) {
if (_me.people) { // return from 'cache'
return $q.resolve(_me.people);
}
// if not 'cached', call 'ajax'
return AjaxGetPeople().then(function (response) {
// add visible property to people
filterPeople(init, response);
_me.people = response;
return response;
});
};
return {
'get': get,
'filterPeople': filterPeople
};
});
Its work's in your JSFiddle, hope help you ;D
Following Filter(ageFilter) will filter depending upon maxAge variable
HTML
<div ng-app='myApp' ng-controller="Main" ng-init="maxAge=30">
<input type="text" ng-model="maxAge">
<li ng-repeat="user in users | ageFilter:maxAge">{{user.name}}</li>
</div>
Script
var myApp = angular.module('myApp', []);
myApp.filter('ageFilter', function() {
return function(input, Maxage) {
var out = [];
for (var i = 0; i < input.length; i++){
if(input[i].age <= Maxage)
out.push(input[i]);
}
return out;
};
});
function Main($scope){
$scope.users = [{name: 'Marcel Sapin',age: 26},
{name: 'Anhel De Niro',age: 42},
{name: 'Johny Resset',age: 30}]
}
At the moment, my Angular app looks like this:
Factory in app.js
StoreApp.factory("DataService", function () {
// create store
var myStore = new store();
// create shopping cart
var myCart = new shoppingCart("Store");
// return data object with store and cart
return {
store: myStore,
cart: myCart
};
});
controller.js
function storeController($scope, $http, $routeParams, $location, DataService) {
$scope.store = DataService.store;
$scope.cart = DataService.cart;
// use routing to pick the selected product
if ($routeParams.productUrlTitle != null) {
$scope.product = $scope.store.getProduct($routeParams.productUrlTitle) || $scope.store.getHero($routeParams.productUrlTitle);
}
$scope.predicate = '-price';
$scope.store.isCart = $location.path() == "/cart";
}
In store.js (below) is where my issue is — currently this.products[] takes inline assignments. I need this to instead load an external JSON file (also below). I've tried several things from including/passing the promise to var myStore = new store();, to actually including $http.get() paired with .then() inside of store.js — to no avail.
store.js
function store() {
this.products = [
new product("USD", 20, "https://foo.jpg", "Name", "Description"),
new product("USD", 20, "https://bar.jpg", "Name", "Description"),
];
}
store.prototype.getProduct = function (urlTitle) {
for (var i = 0; i < this.products.length; i++) {
if (this.products[i].urlTitle == urlTitle)
return this.products[i];
}
return null;
}
payload.json
[
{
"currency": "usd",
"cost": 1000,
"image_url": "https://whatever.domain/someimage.jpg",
"id": "xyz",
"name": "A title",
"description": "Some details"
},
...
]
For those interested, my project is based on this: A Shopping Cart Application Built with AngularJS.
Many thanks in advance.
Update
I was able to accomplish what I wanted, but I'm not certain it's the best (Read: correct) way to. In short, I added a new factory called "InventoryService" that I pass to my controller.
app.js
// New Factory Added
StoreApp.factory('InventoryService', ['$http', '$rootScope',
function ($http, $rootScope) {
var inventory = [];
return {
getInventory: function () {
return $http.get('http://localhost/ShoppingCart/payload.json').then(function (response) {
inventory = response;
$rootScope.$broadcast('handleInventoryService', inventory);
return inventory;
})
}
};
}
]);
controller.js
function storeController($scope, $http, $routeParams, $location, InventoryService, DataService) {
$scope.name = 'inventory';
(function () {
InventoryService.getInventory().then(function (inventory) {
$scope.inventory = inventory;
for (var i = 0; i < $scope.inventory.data.length; i++) {
if ($scope.inventory.data[i].id == '11ca3ea26f0e431eb996a401f292581f2') {
DataService.store.hero.push(
new product(
$scope.inventory.data[i].id,
$scope.inventory.data[i].image_url,
$scope.inventory.data[i].name,
$scope.inventory.data[i].description,
$scope.inventory.data[i].cost
)
);
} else {
DataService.store.products.push(
new product(
$scope.inventory.data[i].id,
$scope.inventory.data[i].image_url,
$scope.inventory.data[i].name,
$scope.inventory.data[i].description,
$scope.inventory.data[i].cost
)
);
}
}
// get store and cart from service
$scope.store = DataService.store;
$scope.cart = DataService.cart;
...
store.html partial
<div ng-include src="'partials/header.html'"></div>
<div ng-repeat="product in store.hero" class="row-fluid">
<div class="span12">
<div class="span4">
<a href="#/products/{{product.urlTitle}}">
<img class="img-polaroid" ng-src="{{product.image_url}}" title="{{product.name}}" />
</a>
</div>
<div class="span8">
<h1 class="tango-tang weight-100">
{{product.name}}
</h1>
<hr />
<div class="row-fluid">
<div class="span7">
<p>
{{product.description}}
</p>
</div>
<div class="span5">
<div class="well">
<h1 class="weight-300 text-center">
{{product.price | currency}}
</h1>
</div>
<button class="btn btn-success btn-medium btn-block" ng-click="cart.addItem(product.sku, product.image_url, product.name, product.price, 1)">
<i class="icon-plus"></i> Add to Cart
</button>
<a href="#/products/{{product.urlTitle}}" class="btn btn-block">
<i class="icon-list"></i> Details
</a>
</div>
</div>
</div>
</div>
</div>
As I outlined in the comment, the InventoryService isn't necessary in your case, $q and $http.get are enough.
Quoted from comments:
You may try to make products and hero both promises, later when HTTP responded, resolve two deferred objects at once.
Code:
App.factory('DataService', function($http, $q) {
function Store() {
var heroDeferred = $q.defer();
var productsDeferred = $q.defer();
this.hero = heroDeferred.promise;
this.products = productsDeferred.promise;
$http.get('/path/to/payload.json').success(function(data) {
var hero = [];
var products = [];
for (var i = 0, len = data.length; i < len; i++) {
var prod = data[i];
if (prod.id === 'xyz') {
hero.push(prod);
} else {
products.push(prod);
}
}
heroDeferred.resolve(hero);
productsDeferred.resolve(products);
});
}
Store.prototype.getProduct = function(urlTitle) {
return this.products.then(function(products) {
for (var i = 0; i < products.length; i++) { // MUST use products, it's the real value; this.products is a promise
if (products[i].urlTitle == urlTitle)
return products[i];
}
return null;
});
};
...
return {
store: new Store()
...
};
});
http://plnkr.co/edit/qff7HYyJnSdEUngeOWVb