In my angularjs service I want an array to be filled as follows:
var results = [
{id: 1, name: 'John'},
{id: 2, name: 'Jane}
]
I want to do this by calling an API. So far I have written this:
function getDataFromAPI() {
$http.get('foo.com/bar.json').then(function(data){
console.log( data.data.employees);
});
}
var results = getDataFromAPI();
When I call results, in my chrome dev tools it will display the results from the json file, but I don't know how to populate the results array.
How can I fill the array?
$http.get (and many other functions in Angular) returns a promise.
var results;
function getDataFromAPI() {
return $http.get('foo.com/bar.json');
}
getDAtaFromAPI().then(function(data) {
results = data;
});
Related
I try to learn angular. currently, i already get data from JSON ( i use local JSON). I try to delete 1 of an array from JSON, its works but after I refresh the page the deleted array come back again. how to update the JSON after I delete array?
customer.html
<tr ng-repeat="experience in experiences">
<td>{{experience.no}}</td>
<td>{{experience.name}}</td>
<td><button ng-click="deleteItem(experience)" class="btn btn-danger">-</button></td>
</tr>
main.js
resolve:{
experiences:['$http',function($http){
return $http.get('scripts/customer.json').then(function(response){
return response.data
})
}]
}
customer json
[
{
"no":1,
"name": "Sarah",
},
{
"no":2,
"name": "Tommy",
}
]
customerCtrl.js
angular.module('app').controller('customerCtrl',['$scope','experiences',function($scope,experiences){
$scope.experiences= experiences;
$scope.deleteItem =function(experience){
var index = $scope.experiences.indexOf(experience);
alert("Deleting DATA: "+ index);
$scope.experiences.splice(index,1);
};
}]);
You're trying to store data in a file using javascript, which is considered as insecure and then hard to implement.
I would suggest you to use LocalStorage instead. Here is a service example you could use in your controller (not tested)
localstorage service
angular.module('app').service('LocalStorage', function(){
return {
save: function(data) {
localStorage.setItem('data',data);
},
get: function(){
return localStorage.getItem('data');
}
};
});
controller
// notice that I injected LocalStorage in controller
angular.module('app').controller('dataPengalamanCtrl',['$scope','experiences',function($scope,experiences, LocalStorage){
$scope.experiences= experiences;
$scope.deleteItem =function(experience){
var index = $scope.experiences.indexOf(experience);
alert("Deleting DATA: "+ index);
$scope.experiences.splice(index,1);
// First transform you're json to a string
var stringifiedData = JSON.stringify( $scope.experiences);
// from there we save data to localStorage
LocalStorage.save(stringifiedData );
};
// if you need, you can load data using :
$scope.data = LocalStorage.get();
Dont forget to save your json in localstorage first, for example with a file like this one :
init.js
var json = [
{
"no":1,
"name": "Sarah",
},
{
"no":2,
"name": "Tommy",
}
];
var strData = JSON.stringify(json);
localstorage.setItem('data', strData);
EDIT
If you want to go with a remote server like myjson.com
Assuming you already saved your json on myjson.com, and url is https://api.myjson.com/bins/8hghd then :
To retrieve your json use $http.get('https://api.myjson.com/bins/8hghd').success(/*...*/).error(/*..*/);
To update your json use $http.put with your json as data (grammar depending of your AngularJS version, see here)
Have a look to the api documentation : http://myjson.com/api
I'm breaking my head on this one.
From my backend I fetch json data for my typeahead input field.
once a value is selected I fetch the full object from the backend by using the unique id that came with the auto complete response.
next thing i do is to push this object into an array and then i itterate over this array to display in the html all fine.
but i would like to test first if the object is already in the array.
for that i'm using array.indexOf property, however for some reason it will never find a match: i hope someone can help me:
here is the code:
the factory:
productServices.factory('Product', ['$resource',
function($resource){
return $resource('http://127.0.0.1:5000/products/:id', {id: '#id'}, {
query: { method:'GET',
isArray:false,
responseType:'json',
cache:true},
update: { method:'PUT' }
fetch product from backend and push to an array:
$scope.onSelect = function ($item, $model, $label) {
$scope.$item = $item
// call the .addProduct service to push the product.get result into a list
acProductService.addProduct(Product.get({ id: $scope.$item.id }));
// this is to retrieve the list
$scope.products = acProductService.getProducts();
// reset field
$scope.selected = '';
};
service to push the data to the array and to list the array (so here on addProduct i would like to test if the object is already in the array)
autocompServices.service('acProductService', function() {
var productList = [];
var addProduct = function(newObj) {
console.log(productList.indexOf(newObj)); ---- here is my issue it will never find the newObj despite i've added it many times
productList.push(newObj);
console.log(productList.indexOf(newObj)); -- does work but i need to check before pushing to the list and not after;
};
var getProducts = function(){
return productList;
};
return {
addProduct: addProduct,
getProducts: getProducts
};
i'm guessing the $resource.get returns something that is unique irrespective of the object retrieved from the back-end is actually unique. any help please.. thanks
I have a product object with a property called category_ids that is an array of ids.
I've added an $update method to my resource factory so I can send a PUT request.
When I PUT, the server receives data that looks like:
id: 1,
description: 'Yada yada',
category_ids: [1,2,3],
product: { id: 1, description: 'Yada yada' } //<-- I need category_ids in here
How can I get the category_ids array into the product node there?
More detail:
I'm just using angular's resource to update:
'use strict'
angular.module('myApp').factory 'Product', ($resource) ->
resource = $resource '/api/v1/products/:id', { id: '#id' },
update:
method: 'PUT'
return resource
Interestingly, this problem only happens with calling instance methods on my object. Calling the class methods on the factory itself works:
currentProduct.$update() <-- This does not give me the format I want!
Product.update(id: currentProduct.id, product: currentProduct) <-- This does :-\
You can add properties to $resource object like
currentProduct.category_ids = [1,2,3];
Now this property becomes request parameter for PUT request.
Lets suppose you have $resource factory name "Product" then following code will work for you
var currentProduct = new Product()
// Bind properties to resource object
currentProduct.id = 1
currentProduct.description = 'Yada yada'
currentProduct.category_ids = [1,2,3]
// Initiate PUT request.
currentProduct.$update()
I believe Rails expecting put request to follow pattern
/product/:id
so when you want to update product you should call it
product.$update({id:product.id});
and that will make request to url
http://api/v1/products?id=1
with request payload like
{"id":"1","description":"Yada yada","category_ids":[1,2,3]}
please see demo here
http://plnkr.co/edit/Utjoj6LirxvzMGSwoffo?p=preview
We would need the code of that $update method, but I suspect it is relying on the this keyword, which is different depending on which object you are calling the function from.
Could you please try this and let us know if it works:
currentProduct.$update.bind(Product) ();
If it does, this means that indeed $update expect this to be Product (which is not the case and is currentProduct in your example instead).
Create a angular service
// Angular Service
angular.module('myApp').factory('Product', function($resource,ENV)
return $resource(ENV.apiEndpoint+'/api/v1/products/:id', {}, {
update: { method: 'PUT' , params:{id:'#id'}}
});
});
In your controller you have to set product object
angular.module('myApp').controller('ProductController',
function ($scope,Product) {
var requestParams = {
id: 1, //Service extracts this parameter to form the url
product: {
id: 1,
description: 'Yada yada'
category_ids: [1,2,3]
}
}
Product.update(requestParams,function(success){
console.log(success)
},function(error){
console.log(error)});
});
I have very simple question about getting data from WebSql
I have DropDown i.e
<select id="selectCatagoryFood" data-role="listview" data-native-menu="true"
ng-init="foodCatagory = foodCatagories.cast[0]"
ng-options="foodCatagory as foodCatagory.text for foodCatagory in foodCatagories.cast"
ng-model="foodCatagory"
ng-change="changeFoodCatagory()">
</select>
now i want to add data init from webSQL. I already get Data from webSql but i am confuse that how to add that data into DropDown
An example or hints maybe very helpful for me.
Update 1 :: Add Controller Code
myApp.controller('foodSelection',function($scope,foodCatagories){
$scope.foodCatagories = foodCatagories;
$scope.changeFoodCatagory = function(){
alert($scope.foodCatagory.value);
}
});
Update 2 webSQL and JayData
_context.onReady({
success: showData,
error: function (error){
console.log(error);
}
});
function showData(){
var option = '';
_context.FoodGroup.forEach(function(FG)
{
option += '<option value="'+FG.FoodGroupID+'">'+FG.Description+'</option>';
}).then(function(){
console.log(option);
});
}
Update 3
var myApp = angular.module('myApp',[]);
myApp.factory('foodCatagories',function(){
var foodCatagories = {};
foodCatagories.cast = [
{
value: "000",
text: "Select Any"
}
];
return foodCatagories;
});
Update 4
One thing that i didn't mention is that I am using JayData for getting data from webSQL to my App
I will try to explain how it works:
EDIT: Live demo
html
Here is your stripped down select.
<select ng-options="item as item.text for item in foodCategories"
ng-model="foodCategory"
ng-required="true"
ng-change="changeFoodCategory()">
</select>
The directive ng-options will fill automatically the option elements in your select. It will take the foodCategories variable from the $scope of your controller and foreach item in the collection, it will use the text property as the label shown (<option>{{item.text}}</option>') and it will select the whole objectitemas the value of the selectedoption. You could also refer to a property as the value like ({{item.text}}). Then yourng-modelwould be set to theid` value of the selected option.
The directive ng-model corresponds to the variable in the $scope of your controller that will hold the value of the selected option.
The directive ng-required allows you to check if a value has been selected. If you are using a form, you can check if the field is valid formName.ngModelName.$valid. See the docs for more details on form validation.
The directive ng-change allows you to execute a function whenever the selected option changes. You may want to pass the ng-model variable to this function as a parameter or call the variable through the $scope inside the controller.
If no default value is set, angular will add an empty option which will be removed when an option is selected.
You did use the ng-init directive to select the first option, but know that you could set the ng-model variable in your controller to the default value you would like or none.
js
Here I tried to simulate your database service by returning a promise in the case that you are doing an async request. I used the $q service to create a promise and $timeout to fake a call to the database.
myApp.factory('DbFoodCategories', function($q, $timeout) {
var foodCategories = [
{ id: 1, text: "Veggies", value: 100 },
{ id: 2, text: "Fruits", value: 50 },
{ id: 3, text: "Pasta", value: 200 },
{ id: 4, text: "Cereals", value: 250 },
{ id: 5, text: "Milk", value: 150 }
];
return {
get: function() {
var deferred = $q.defer();
// Your call to the database in place of the $timeout
$timeout(function() {
var chance = Math.random() > 0.25;
if (chance) {
// if the call is successfull, return data to controller
deferred.resolve(foodCategories);
}
else {
// if the call failed, return an error message
deferred.reject("Error");
}
}, 500);
/* // your code
_context.onReady({
success: function() {
deferred.resolve(_contect.FoodGroup);
},
error: function (error){
deferred.reject("Error");
}
});
*/
// return a promise that we will send a result soon back to the controller, but not now
return deferred.promise;
},
insert: function(item) {
/* ... */
},
update: function(item) {
/* ... */
},
remove: function(item) {
/* ... */
}
};
});
In your controller you set the variables that will be used in your view. So you can call your DbFoodCategories service to load the data into $scope.foodCategories, and set a default value in $scope.foodCategory that will be used to set the selected option.
myApp.controller('FoodSelection',function($scope, DbFoodCategories){
DbFoodCategories.get().then(
// the callback if the request was successfull
function (response) {
$scope.foodCategories = response; //response is the data we sent from the service
},
// the callback if an error occured
function (response) {
// response is the error message we set in the service
// do something like display the message
}
);
// $scope.foodCategory = defaultValue;
$scope.changeFoodCategory = function() {
alert($scope.foodCatagory.value);
}
});
I hope that this helped you understand more in detail what is happening!
See this example and how use $apply to update the data in scope.
in the new version we released a new module to support AngularJS. We've started to document how to use it, you can find the first blogpost here
With this you should be able to create your dropdown easily, no need to create the options manually. Something like this should do the trick:
myApp.controller('foodSelection',function($scope, $data) {
$scope.foodCatagories = [];
...
_context.onReady()
.then(function() {
$scope.foodCatagories = _context.FoodGroup.toLiveArray();
});
});
provided that FoodGroup has the right fields, of course
I am trying to populate a select using below.
View: Backbone.View.extend({
initialize: function () {
this.setElement($('#templatePlaceholder'));
},
bindings: {
'select#List': {
observe: 'ddList',
selectOptions: {
collection: Q.when(getSelects.execute()).then(function (data) {
console.dir(data);
return data;
})
}
}
},
console returns an array object:
[ { value: 1, label: "a" }, { value: 2, label: "b" } ]
But I get nothing.
If I define collection as:
collection: function () { return [{ value: 1, label: "a" },{ value: 2, label: "b" }];}
then all works fine.
There is potentially a couple of problems with this: that asynchronous code is executing immediately as View is being assigned which may not be desired; and collection is getting assigned to the result of executing that promise, not whatever is being returned by return data.
Some solutions:
1) You could bootstrap your select options on page load. This is a popular pattern in single page or Backbone apps. Basically, you have the backend put together json data-structures of common data and then render it to the page as a javascript variable. So the server side template (jsp, erb, php) would look something like this:
<!DOCTYPE html>
...
<script type="text/javascript">
window.bootstrap = { users: <%= userjson %>, ddlist: <%= ddlistjson %> };
</script>
...
This method is recommended for performance and convenience.
2) If you have the option to run getSelects.execute() synchronously - for example if it is a jQuery ajax request, run it with the async:false option - then you could execute it in a couple of places in the view. During initialize will fetch the data when the view is actually constructed. Or you could assign your collection binding with a function that runs the getSelects routine, which blocks and then returns the data:
collection: function() {
var collection = [];
// Assumes that getSelects.execute() will block and run synchronously.
Q.when(getSelects.execute()).then(function (data) {
collection = data;
});
return collection;
}
This method is not recommended as it could leave your UI in a funky state as it blocks other javascript from running, and could potentially get hung up.