Why AngularJS is changing values of the objects? - javascript

My AngularJS service code -
this.getEducation = function (id) {
var url = 'SOME_URL/?party_id=' + id;
var deferred = $q.defer();
$http.get(url).
success(function (data, status, headers, config) {
console.log(data);
deferred.resolve(data);
}).
error(function (data, status, headers, config) {
console.log("could not get education info");
deferred.reject(data);
});
return deferred.promise;
}
Now, my service is returning a data like this -
[
{
"id": 22,
"party_id": 9,
...
"university": "UoP",
"created_at": "2015-07-13 17:09:52",
"degree": "BE"
},
{
"id": 23,
"party_id": 9,
...
"university": "UoP",
"created_at": "2015-07-13 17:11:06",
"degree": "ME"
}
]
Now, here's the problem - when the data being resolved in promise, contains following array -
[
{
"id": 22,
"party_id": 9,
...
"university": "UoP",
"created_at": "2015-07-13 17:09:52",
"degree": "BE"
},
{
"id": 23,
"party_id": 9,
...
"university": null,
"created_at": "2015-07-13 17:11:06",
"degree": null
}
]
So, my question is, WHY AngularJS setting some values of my array elements to null ???
P.S. I'm using the data retrieved by this in controller, assigning it to scope variable, and doing ng-repeat on forms.
Edit :
My controller code is as follows
$scope.educationInformations = [];
$scope.setEducation = function () {
EducationProvider.getEducation(id).then(
function (educations) {
angular.forEach(educations, function(education){
console.log(education);
$scope.educationInformations.push({education:education});
console.log($scope.educationInformations);
})
});
};
THIS works, (console log is accurate)
Now, This is my template code.
When this is used,
<div ng-repeat="educationInfo in educationInformations">
<input-text ng-model="educationInfo.education.university"></input-text>
</div>
Now input-text is a directive created by me..
Directive code -
.directive('inputText', function () {
return {
templateUrl: 'views/inputText.html',
restrict: 'E',
scope: {
ngModel: '='
}
};
});
Directive template
<input class="form-control"
ng-model="ngModel" ng-init="ngModel = null">

Edit the directive template code as follows
<input class="form-control"
ng-model="ngModel" ng-init="ngModel">
Your code was setting ng-model to null ( ng-init = "ngModel = null ), as you have two way binding with controller, this initialization to null would affect the controller scope objects.

Related

How to pass the array object in $http.get method in angularjs

I want to pass Array object in $http.get(). Previously all information is stored in data.json file, But I don't want to use file. Want to define the Array of object as $scope.data in controller.
Please find DEMO
http://plnkr.co/edit/X5ZC3UGey4Zjos7W01U1?p=preview
Working DEMO http://plnkr.co/edit/o6EeKnC8oFEq3GCRsQgp?p=preview
here we are using data.json. I want to define data inside data.json in Controller, Plz tell me how to dd
.controller('QuestionCtrl', ['$scope', '$http', function ($scope, $http) {
$scope.questions = [];
$scope.data = {
"questions": [
{
"question": "Qw1",
"answers": [
{
"answers": "An1",
"value": 25
},
{
"answers": "An2",
"value": 50
},
{
"answers": "An3",
"value": 75
},
{
"answers": "An4",
"value": 100
}
]
},
{
"question": "Qw2",
"answers": [
{
"answers": "An1",
"value": 25
},
{
"answers": "An2",
"value": 50
},
{
"answers": "An3",
"value": 75
},
{
"answers": "An4",
"value": 100
}
]
}
]
}
$http
.get(JSON.stringify($scope.data))
.then(function(response){
$scope.questions = response.data.questions;
});
}])
I'm using this, and it works great for me
$http.get('url', {params: yourArray}).then(function (result) {
//do sth with data
});
HTTP GET request can't contain data to be sent to the server. You can add a query string to the request. $http option for it is params.
$http({
url: 'example.com',
method: "GET",
params: {...}
});
You dont need to use $http.get() if the data is directly available in controller.
You can use $scope.data instead of $scope.questions. ie in your html file use
{{data.questions[0].question}}
<h2>answer 1</h2>
<p>{{data.questions[0].answers[0].value}}</p>
<p>{{data.questions[0].answers[0].answers}}</p>
I have tried this way and it is working fine:
For example in your controller you have any array like arr variable
var data = Array;
data['Id'] = "1";
data['Name'] ="Test User";
data['UserName'] = "test_user";
data['Email'] = "test#gmail.com";
data['Address'] = "Test Address";
data['Action'] = 'Create';
To pass this array you can use like this
$scope.users = data;
The controller send an array in view page as the variable users
and you can use something like this
ng-repeat="user in users"
Note: this will work for two dimensional array and one dimensional array.
AngularJS has $http service, to get data asynchronously. So it can return any type of data(variable, array, string).
It is better to store data in some common place. Let me show factory pattern which is used for sharing data between controllers.
At first, you should create yourFactory.js file and write the following code:
(function () {
var yourFactory = function () {
var persons = [
{
id: 1,
name: 'Jon',
},
{
id: 2,
name: 'Ben',
},
{
id: 3,
name: 'Joseph',
},
{
id: 4,
name: 'Adam',
}
];
var factory = {};
factory.getPersons = function () {
return persons;
};
return factory;
};
angular.module('personsApp').factory('personsFactory', yourFactory);
}());
and some your controller can use data(just create new .js file for the following controller):
(function()
{
debugger;
var yourController=function($scope, yourFactory) {
/*alert('a1');*/
debugger;
function init() {
debugger;
$scope.yourData=yourFactory.getPersons();
}
init();
};
yourController.$inject=['$scope', 'yourFactory'];
angular.module('yourAppl').controller('yourController', yourController);
}());

AngularJS: Make isolate scope directive template bind to parent scope

I've been struggling with Angular's isolate scope for over 24hrs now. Here's my scenario: I have an ng-repeat iterating over an array of objects from which I want to use a custom directive to either generate a <select> or <input> based on the field_type property of the current object being iterated. This means I'll have to generate the template and $compile in the post-link function of the directive since I have no access to the iterated object in the template function.
Everything works as expected, apart from the actual binding of the generated template to the controller (vm) in my outer scope. I think my approach (adding this in the template string: ng-model="vm.prodAttribs.' + attr.attribute_code +'") may be wrong, and would appreciate pointers in the right direction. Thanks!
See sample code below:
directives:
directives.directive('productAttributeWrapper', ['$compile', function($compile){
//this directive exists solely to provide 'productAttribute' directive access to the parent scope
return {
restrict: 'A',
scope: false,
controller: function($scope, $element, $attrs){
this.compile = function (element) {
$compile(element)($scope);
console.log('$scope.prodAttribs in directive: ', $scope.prodAttribs);
};
}
}
}]);
directives.directive('productAttribute', ['$compile', function($compile){
return {
restrict: 'A',
require: '^productAttributeWrapper', //use the wrapper's controller
scope: {
attribModel: '=',
prodAttribute: '=productAttribute', //binding to the model being iterated by ng-repeat
},
link: function(scope, element, attrs, ctrl){
var template = '';
var attr = scope.prodAttribute;
if(!attr) return;
switch(attr.attribute_field_type.toLowerCase()){
case 'textfield':
template =
'<input type="text" id="'+attr.attribute_code+'" ng-model="vm.prodAttribs.' + attr.attribute_code +'">';
break;
case 'dropdown':
template = [
'<select class="cvl" id="'+attr.attribute_code+'" ng-model="vm.prodAttribs.' + attr.attribute_code +'">',
'#cvl_option_values',
'\n</select>'
].join('');
var options = '\n<option value="">Select One</option>';
for(var i=0; i<attr.cvl_option_values.length; i++) {
var optionVal = attr.cvl_option_values[i].value;
options += '\n<option value="'+optionVal+'">' + attr.cvl_option_values[i].value + '</option>';
}
template = template.replace('#cvl_option_values', options);
break;
}
element.html(template);
ctrl.compile(element.html()); //try to bind template to outer scope
}
}
}]);
html:
<div ng-controller="ProductController as vm">
<div product-attribute="attrib" ng-repeat="attrib in vm.all_attribs"></div>
</div>
controller:
app.controller('ProductDetailsController', function(){
var vm = this;
//also added the property to $scope to see if i could access it there
$scope.prodAttribs = vm.prodAttribs = {
name: '',
description: '',
price: [0.0],
condition: null
}
vm.all_attributes = [
{
"attribute_id": 1210,
"attribute_display_name": "Product Type",
"attribute_code": "product_type",
"attribute_field_type": "Textfield",
"cvl_option_values": [],
"validation_rules": {}
},
{
"attribute_id": 902,
"attribute_display_name": "VAT",
"attribute_code": "vat",
"attribute_field_type": "dropdown",
"cvl_option_values": [
{
"option_id": "5",
"value": "5%"
},
{
"option_id": "6",
"value": "Exempt"
}
],
"validation_rules": {}
}];
})
issue is probably here :
element.html(template);
ctrl.compile(element.html()); //try to bind template to outer scope
element.html() returns a html as a string, not the ACTUAL dom content, so what you inserted into your directive's element is never actually compiled by angular, explaining your (absence of) behaviour.
element.append(ctrl.compile(template));
should work way better.
For directive requiring parent controller, I would also change your ctrl.compile method (renamed to insertAndCompile here)
ctrl.insertAndCompile = function(content) {
$compile(content)($scope, function(clone) {
$element.append(clone);
}
}
You would just have to call it this way :
ctrl.insertAndCompile(template);
instead of the 2 lines I gave as first answer.
I would suggest to use templates instead of html compilation manually. The solution is much simpler:
Controller would contain data declaration:
app.controller('ProductDetailsController', function($scope) {
$scope.prodAttribs = {
name: '',
description: '',
price: [0.0],
condition: null
}
$scope.all_attribs = [{
"attribute_id": 1210,
"attribute_display_name": "Product Type",
"attribute_code": "product_type",
"attribute_field_type": "Textfield",
"cvl_option_values": [],
"validation_rules": {}
}, {
"attribute_id": 902,
"attribute_display_name": "VAT",
"attribute_code": "vat",
"attribute_field_type": "dropdown",
"cvl_option_values": [{
"option_id": "5",
"value": "5%"
}, {
"option_id": "6",
"value": "Exempt"
}],
"validation_rules": {}
}];
});
Your directive would be as simple as that:
app.directive('productAttribute', function() {
return {
restrict: 'A',
scope: {
attribModel: '=',
prodAttribute: '=productAttribute'
},
templateUrl: 'template.html',
controller: function($scope) {}
}
});
template.html would be:
<div>
<select ng-show="prodAttribute.attribute_field_type.toLowerCase() == 'dropdown'" class="cvl" id="" ng-model="prodAttribs.attribute_code">
<option value="">Select One</option>
<option ng-repeat="item in prodAttribute.cvl_option_values track by $index" value="{{item.value}}">{{item.value}}</option>
</select>
<input ng-show="prodAttribute.attribute_field_type.toLowerCase() == 'textfield'" type="text" id="{{prodAttribute.attribute_code}}" ng-model="prodAttribute.attribute_code">
</div>
And your html:
<div ng-controller="ProductController">
<div ng-repeat="attrib in all_attribs" product-attribute="attrib">{{attrib}}</div>
</div>

http json file retrieving with IONIC and AngularJS

I am working on an product reviewing app based on ionic framework.
The app will consume REST service in JSON format.
Because Im not able to retireve data directly from the locally deployed website, i created a json demo file:
[{
"index": 0,
"marque": "labore",
"estAutorise": 0,
"name": "Jennifer Simmons"
},
{
"index": 1,
"marque": "duis",
"estAutorise": 0,
"name": "Beatriz Hale"
},
{
"index": 2,
"marque": "pariatur",
"estAutorise": 1,
"name": "Richmond Garner"
}
]
here is my services.js:
angular.module('starter.services', [])
.factory('Recettes', function($http) {
var recettes = [];
var produits = [];
$http.get('test.json').success(function(data) {
alert("success"); //to check the seccess responce
produits= data;
});
return {
...
produits: function() {
return produits;
},
....
Before this, I implemented products and recettes directly and it works just fine. And now, I recieve the success alert but the data seems to be invalid.
My controller:
angular.module('starter.controllers', [])
.controller('DashCtrl', function($scope, Recettes) {
$scope.produits = Recettes.produits();
})
...
So my question is how can i fix the data binding problem ?
And If it works with .json file should it work for rest services as well (Content-Type: application/json )?
Thank you.

Why is my json data not being fetched from an each loop with jquery?

I have a set of data that is created/pulled from a url that has already got parsed json data like so:
[
{
"id": 1,
"school_name": "another school in essex",
"website": null,
"book_id": 27,
"url": "http://localhost:3000/schools/1.json"
},
{
"id": 2,
"school_name": "ddffdfd",
"website": null,
"book_id": 31,
"url": "http://localhost:3000/schools/2.json"
},
{
"id": 3,
"school_name": "ddfdfdffd",
"website": null,
"book_id": 31,
"url": "http://localhost:3000/schools/3.json"
},
{
"id": 4,
"school_name": "4545455454",
"website": null,
"book_id": 31,
"url": "http://localhost:3000/schools/4.json"
}
]
I have got a .each loop that grabs the data and assigns it to (city) parameter so I can grab that city parameter and loop through and just grab what I want from that json out put and use.
var info = '/schools.json';
$.get(info, function(response) {
var jsonData = response
var mapContent = $('').html();
var json = jsonData;
}
function setMarkers(map, json) {
jQuery.each(json, function (index, city) {
console.log(city[id]);
}
}
When I try and access the json object in the .each loop above it gives nothing. How can I access the id from each of the json outputs?
Cheers
Try this, you didn't called the setMarkers function, also, you didn't close the $.get function. Also when you get values from an object you should use obj['value'] or obj.value
var info = '/schools.json';
$.get(info, {}, function(response) {
var mapContent = $('').html();
setMarkers(mapContent, response);
}, 'json');
function setMarkers(map, json) {
jQuery.each(json, function (index, city) {
console.log(city['id']);
}
}
$.get(info,PARAMS, function(response) {
var jsonData = response
var mapContent = $('').html();
var json = jsonData;
},"json");
I think you forgot the closing ');' and a function parameter: 'PARAMS' that can be null
Just try adding "json" as final argument.
Hope it helps
your code should return ReferenceEerror: id is not defined. use city["id"] or city.id instead.
And check that json is valid json object, not string

Extract NodeJS Response into HTML

I want to take this request on NodeJS
Stripe.apiKey = "sk_test_AJKebDsM6QFiK8VpJ06Vq1M1";
stripe.balance.retrieve(function(err, balance) {
// asynchronously called
});
which an example response is
{
"pending": [
{
"amount": 0,
"currency": "usd"
}
],
"available": [
{
"amount": 0,
"currency": "usd"
}
],
"livemode": false,
"object": "balance"
}
and extract the balance information to place it into an HTML label.
How would I go about doing this? Can I pass the response to Angular and then link that to HTML?
You have to have that being served in a route (something like /balance) and then have your angular app consuming it:
If you're using express as your web framework, here's an example (from the top of my head - not tested):
app.get('/balance', function (request, response) {
stripe.balance.retrieve(function(err, balance) {
response.send(balance);
});
});
and here your angular app:
angular.module('myApp', [])
.controller('BalanceController', function ($scope, $http) {
$http.get('/balance').then(function (response) {
$scope.balance = response.data;
});
});

Categories

Resources