AngularJS Read From JSON Returning Nothing - javascript

I am building an application that has a button that loads up help based on IDs from the JSON, when I have the JSON in the controller.js I see it on the web page but if I do it externally I do not see anything. I feel I am missing something extremely simple but may be over looking it. Any ideas?
controllerNEW.js
app.factory("UserService", function($rootScope, $http){
function getFile(){
return $http.get('stat.json').then(function(data) {
return data;
});
}
return{statErr: getFile,
//hide the displayed tooltip based on its id
hideTooltip: function(key, scopes, data)
{
controllerOLD.js
app.factory("UserService", function($rootScope){
return{
statErr: [
{
selector: "#userEmail",
fieldTitle: "Email",
placement: "right",
content: "test",
offsetTop: 500,
correctKey: "#test",
inErrorList: false
},
{
selector: "#userId",
fieldId: "id1",
fieldTitle: "ID",
placement: "right",
content: " number should contain 4 zeroes '...0000...'",
offsetTop: 500,
correctKey: "0000",
inErrorList: false
}
],
//hide the displayed tooltip based on its id
hideTooltip: function(key, scopes, data)
{

The issue is getFile() returns a promise not the data itself. It is true that you have a .then(function(data) {return data; });, but, .then() also returns a promise.
So to fix this issue, in your actual code, after you call getFile() you also need to add .then() to have access to your data:
getFile().then(function(data){
// now you have access to your data
})

you need to access the data object in the response object.
example:
var jsonResponse = $http.get('content.json').then(function(response) {
return response.data;
});

In your example, data is the whole response to your request, including headers and status. To see your data from the 'stat.json' file, you would access the data object of your data. So, the change is.
function getFile(){
return $http.get('stat.json').then(function(data) {
return data.data;
});
}

you can try something like this
$http.get('stat.json').then(function(result){
$scope.dataset = result.data
console.log($scope.dataset)
},function(error){
console.log(error)
})

Related

JQuery Ajax Autocomplete Not Displaying Result

I have a form that load Jquery autocomplete, I got the result, but it does not shows up (blank with border). Just like this image:
Here's my JQuery Code:
<script type="text/javascript">
// Customer
$('input[name=\'customer\']').autocomplete({
delay: 500,
source: function (request, response) {
$.ajax({
url: 'getCustomer.php?filter_name=' + encodeURIComponent(request.term),
dataType: 'json',
success: function (json) {
response($.map(json, function (item) {
return {
label: item.c_name,
value: item.c_id
}
}));
}
});
},
select: function (event, ui) {
$('input[name=\'customer\']').val(ui.item.label);
$('input[name=\'customer_id\']').val(ui.item.value);
return false;
},
focus: function (event, ui) {
return false;
}
});
</script>
And here's AJAX result:
Anyone here have same problem before? I'm using Admin LTE template by the way. And still wondering what's wrong with my code. I have tried import other Jquery-min-js but still not working. Still displayed like that (blank bordered). FYI: there's no error at console log.
I am guessing that the AJAX response you've shown (as an image) is the actual response from the server, before your $.map() has modified it.
Your $.map() function iterates over that json response from the server, and it tries to use the c_name and c_id property names in each element. But the json from the server does not include those property names - it has customer_id and name.
So the $.map() creates a bunch of empty elements, and passes them on to autocomplete. Autocomplete then has a set of elements to display, but without any labels, which is why you see the dropdown with empty horizontal lines, rather than just nothing at all, which is what you'd see when there's no response/match at all.
You simply need to use the same property names you have in your AJAX:
response($.map(json, function (item) {
return {
label: item.name,
value: item.customer_id
}
}));

Object property becomes null after chrome.storage.sync.set

I'm building a chrome extension and have encountered a bug I cannot wrap my head around. The problem is a single object property that becomes null in chromes' storage.
I'm testing this by doing:
console.log("pre-storage", settings);
var obj = {};
obj[storage_key] = settings;
chrome.storage.sync.set(obj, function() {
chrome.storage.sync.get(storage_key, function(data) {
console.log("post-storage", data[storage_key]);
});
});
This is the output:
pre-storage, Object {
...
soundClip: Object {
options: Array[5],
selected: Object {
label: "Soft2",
value: "snd/soft2.wav"
}
}
}
post-storage, Object {
...
soundClip: Object {
options: Array[5],
selected: null
}
}
Storing JSON.parse(JSON.stringify(obj)) instead of obj directly seems to fix this. Anyone have any ideas what might cause this? Any help is appreciated!
Edit: Making a deep copy of obj does not fix it.
Edit2: I should expand on how settings.soundClip is set. I'm using Angular (1.x) and I'm using a custom select directive. The stripped down directive looks like this:
function mySelect() {
return {
restrict: "E",
templateUrl: "mySelect.html",
scope: {
options: "=",
selected: "="
},
link: function (scope) {
scope.select = function (item) {
scope.selected = item;
};
}
}
}
Directive template view (mySelect.html):
<div>
<div ng-repeat="item in options track by $index"
ng-click="select(item)">
</div>
</div>
The properties are then two-way bound like this:
<my-select selected="settings.soundClip.selected"
options="settings.soundClip.options">
</my-select >
Since calling JSON.parse(JSON.stringify(obj)) seems to fix it, my guess is that you're having a problem with encoding your settings object with a variable instead of a string. See the answer here which might help.
Is it possible that the total quota (or per item) is being hit? Consider displaying the runtime.lastError on the set callback to see if there are any error messages.
chrome.storage.sync.set(obj, function() {
console.log('Error', runtime.lastError);
chrome.storage.sync.get(storage_key, function(data) {
console.log("post-storage", data[storage_key]);
});
});
See the limits here chrome.storage.sync.set

Not all attributes of JavaScript object being mapped into JSON

I'm using Inkfilepicker.io for picture uploading on a project I'm working on. When you upload a picture, it returns a JavaScript object with some data in it. I need more, though. So I query their API using their SDK to get more. I then add this information to each object. Lastly, I post these objects using jQuery to process it on the backend. However, none of the second batch of information goes along for the ride on the backend. I manually used JSON.stringify() to see what the data looked like before it was posted. The new data was not included.
fp.pickAndStore({multiple: true}, {}, function (InkBlobs)
{
InkBlobs = $.map(InkBlobs, function(blobio, index)
{
fp.stat(blobio, {
width: true,
height: true
}, function(meta) {
blobio.width = meta.width;
blobio.height = meta.height;
});
return blobio;
});
console.log(InkBlobs);
console.log(JSON.stringify(InkBlobs));
$.post('/picture', { blobs: InkBlobs }, function(data)
{
console.log(data);
}, 'json');
});
How can I make sure all of the attributes get sent?
UPDATE
The string created by the JSON.stringify() looks like the following:
[{"url":"https://www.filepicker.io/api/file/PinzEEUlRhSCpc4dYa0w","filename":"browserWars.jpeg","mimetype":"image/jpeg","size":34284,"key":"Vx1xEuqHTKKCM4hjR6LL_browserWars.jpeg","container":"kandidlypictures","isWriteable":true},{"url":"https://www.filepicker.io/api/file/wdnWcCUWStiBxbrONeSN","filename":"1440-music-is-the-food.jpg","mimetype":"image/jpeg","size":97814,"key":"0RrSFSQBTCiifZ8ZkuIj_1440-music-is-the-food.jpg","container":"kandidlypictures","isWriteable":true},{"url":"https://www.filepicker.io/api/file/trdKhlORPCJEu3JRbPYf","filename":"any_browser.jpeg","mimetype":"image/jpeg","size":271194,"key":"1aJNE9MSEyEiAJZAacfD_any_browser.jpeg","container":"kandidlypictures","isWriteable":true}]
The expected output should also include a width and height for each object.
Use a separate named function:
var data = {
width: true,
height: true
};
var fn = function fn(meta)
{
blobio.width = meta.width;
blobio.height = meta.height;
$.post('/picture', { blobs: InkBlobs }, function(data)
{
console.log(data);
}, 'json');
};
fp.statSync(blobio, data, fn)
Or use statSync since stat is asynchronous:
fp.statSync(blobio, {
width: true,
height: true
}, function(meta) {
blobio.width = meta.width;
blobio.height = meta.height;
});
References
Fun with Named Functions
statSync

How to alter the data returned by $resource in Angular.js?

I'm using an API that returns JSON data in this format:
{
paging: {
previous: null,
next: null
},
data: [
{ title: 'First Item' },
{ title: 'Second Item' },
...
]
}
I'm using Angular's $resource service to fetch this data.
My code - which is located in a controller - goes something like this:
var Entity = $resource('/api/entities');
var entities = $scope.entities = Entity.get();
And then, in the view, I can display the data like this:
<ul>
<li ng-repeat="entity in entities.data">{{entity.title}}</<li>
</ul>
It all works fine, but:
I'd rather expose only the contents of entities.data to the view, instead of the whole entities object. How can I intercept the data returned by the GET request to modify it before it populates $scope.entities?
Correlated question: since I am fetching an array of data, it would be cleaner to use Entity.query() instead of Entity.get(). But if I use Entity.query() in the code above, I get an error "TypeError: Object # has no method 'push'". This makes sense, since the API is returning an object instead of an array (hence, no 'push' method on the object). Again, if I could extract the .data attribute from the response, I'd have an array.
Following these indications by Dan Boyon, I managed to customize the default $resource service and to override the .get() or .query() methods, but I'm not sure where to go from there.
I don't think you need to modify the get or query defaults. Just use the success callback to do what you want. It should be more robust as well.
Entity.get(
{}, //params
function (data) { //success
$scope.entities = data.data;
},
function (data) { //failure
//error handling goes here
});
Html will be cleaner, too:
<ul>
<li ng-repeat="entity in entities">{{entity.title}}</<li>
</ul>
By the way, I usually declare services for my resources and then inject them into my controllers as I need them.
myServices.factory('Entity', ['$resource', function ($resource) {
return $resource('/api/entities', {}, {
});
}]);
You can use the Response Transformer (transformResponse) like this:
$resource('/api/entities', {}, {
query: {
method: 'GET',
responseType: 'json',
isArray: true,
transformResponse: function (response) {
return response.data;
}
}
});
This code modifies the "query" method behaviour, you can do the same for "get" ... !

Load data into a Backbone collection from JSON file?

I'm trying to load some data into a Backbone Collection from a local JSON file, using this very basic code:
window.Student = Backbone.Model.extend({
});
window.Students = Backbone.Collection.extend({
model: Student,
});
window.AllStudents = new Students();
AllStudents.fetch({ url: "/init.json"});
console.log('AllStudents', AllStudents);
In the console statement, AllStudents is empty. But init.json is definitely being loaded. It looks like this:
[
{ text: "Amy", grade: 5 },
{ text: "Angeline", grade: 26 },
{ text: "Anna", grade: 55 }
]
What am I doing wrong?
UPDATE: I've also tried adding a reset listener above the .fetch() call, but that's not firing either:
AllStudents.bind("reset", function() {
alert('hello world');
});
AllStudents.fetch({ url: "/init.json"});
No alert appears.
UPDATE 2: Trying this script (reproduced here in full):
$(function(){
window.Student = Backbone.Model.extend({
});
window.Students = Backbone.Collection.extend({
model: Student,
});
window.AllStudents = new Students();
AllStudents.url = "/init.json";
AllStudents.bind('reset', function() {
console.log('hello world');
});
AllStudents.fetch();
AllStudents.fetch({ url: "/init.json", success: function() {
console.log(AllStudents);
}});
AllStudents.fetch({ url: "/init.json" }).complete(function() {
console.log(AllStudents);
});
});
Only one console statement even appears, in the third fetch() call, and it's an empty object.
I'm now absolutely baffled. What am I doing wrong?
The JSON file is being served as application/json, so it's nothing to do with that.
The attribute names and non-numeric attribute values in your JSON file must be double quoted (" ") . Single quotes or no-quotes produces errors and response object is not created that could be used to create the models and populate the collection.
So. If you change the json file content to :
[
{ "text": "Amy", grade: 5 },
{ "text": "Angeline", grade: 26 },
{ "text": "Anna", grade: 55 }
]
you should see the non-empty collection object.
You can change your code to see both success and failure as below:
AllStudents.fetch({
url: "/init.json",
success: function() {
console.log("JSON file load was successful", AllStudents);
},
error: function(){
console.log('There was some error in loading and processing the JSON file');
}
});
For more details, probably it will be a good idea to look in to the way ajax response objects are created.
I/O operations in javascript are almost always asynchronous, and so it is with Backbone as well. That means that just because AllStudents.fetch has returned, it hasn't fetched the data yet. So when you hit your console.log statement, the resources has not yet been fetched. You should pass a callback to fetch:
AllStudents.fetch({ url: "/init.json", success: function() {
console.log(AllStudents);
}});
Or optionally, use the new promise feature in jQuery (fetch will return a promise):
AllStudents.fetch({ url: "/init.json" }).complete(function() {
console.log(AllStudents);
});
fetch() returns a 'success' notification as already stated, but that just means that the server request was successful. fetch() brought back some JSON, but it still needs to stuff it into the collection.
The collection fires a 'reset' event when it's contents have been updated. That is when the collection is ready to use...
AllStudents.bind('reset', function () { alert('AllStudents bind event fired.'); });
It looks like you had this in your first update. The only thing I did differently was to put fetch() in front of the event binding.
I think you need to add {add:true} to the options of fetch,
if you assigned the fetch to a variable, you would get the result as well,
but then its not inside the collection you wanted

Categories

Resources