emberjs - processing data returned from ajax call - ajax

I'm sure this is very simple but ...
I have an ember route which uses an Ajax call to retrieve an array of data. I want to create an array of model objects from that array.
When I try to create instances of the model in question I get an error
Cannot read property '_attributes' of null TypeError: Cannot read property '_attributes' of null
To try to define what the issue was I created a couple of model instances independently of the data being returned from the Ajax call, for instance :
var testPccB = ParentCostCentre.create({cceClientCode : "ABC" });
And the error occurs there as well.
The entire route code looks like this :
import Ember from 'ember';
import ParentCostCentre from "../models/parentcostcentre";
export default Ember.Route.extend({
model() {
return Ember.RSVP.hash({
costcentres: this.store.findAll('costcentre'),
parentcostcentres: this.testFindParents(),
})
},
testFindParents: function () {
var result = [];
return new Ember.RSVP.Promise(function (resolve, reject) {
const theDrvId = 888;
const theClientCode = 'ABC';
const theCceIdentifier = 'XYZXY';
console.log("About to create testPccA");
//this works
var testPccA = ParentCostCentre.create();
console.log("Finished create testPccA");
console.log("About to create testPccB");
//this generates the error
var testPccB = ParentCostCentre.create({cceClientCode : "ABC" });
console.log("Finished create testPccB");
var theUrl = "api/parentcostcentres/" + theDrvId + "/" + theClientCode + "/" + theCceIdentifier ;
Ember.$.ajax({
type: 'GET',
url: theUrl,
success: function (data) {
data.forEach(function (item) {
result.push(ParentCostCentre.create(item));
});
resolve(result);
},
error: function (request, textStatus, error) {
console.log(error);
reject(error);
}
});
});
},
setupController(controller, model) {
controller.set('costcentres', model.costcentres);
controller.set('parentcostcentres', model.parentcostcentres);
}
});
Is there something I'm failing to do here which would allow this to work ?
EDIT 1:
This is what the parentcostcentre model looks like :
import DS from 'ember-data';
export default DS.Model.extend({
cceClientCode: DS.attr('string'),
cceIdentifier: DS.attr('string'),
cciActiveFrom: DS.attr('date'),
cciActiveTo: DS.attr('date'),
cciAutoid: DS.attr('number'),
cciCcGeoLevel: DS.attr('number'),
cciCceId: DS.attr('number'),
cciDescription: DS.attr('string'),
cciPraId: DS.attr('number'),
cciMatEmpId: DS.attr('number'),
cciIsDisabled: DS.attr('number'),
cciPostsummFlag: DS.attr('string'),
cciTdEmpId: DS.attr('number'),
emiActiveToPra: DS.attr('date'),
emiActiveToTd: DS.attr('date'),
emiEmailAddressPra: DS.attr('string'),
emiEmailAddressTd: DS.attr('string'),
emiNameFamilyPra: DS.attr('string'),
emiNameFamilyTd: DS.attr('string'),
emiNameFirstPra: DS.attr('string'),
emiNameFirstTd: DS.attr('string')
});
EDIT 2
For what it's worth the data returned by the API call is shown below. I'm not sure how relevant that is given that even this processing ...
var testPccB = ParentCostCentre.create({cceClientCode : "ABC" });
... generates the error but I include it for completeness.
[
{
"id": 5101,
"cceClientCode": "ABC",
"cceIdentifier": "XYZXY",
"cciAutoid": 81415,
"cciCceId": 5111,
"cciActiveFrom": "2017-03-27T11:47:23",
"cciActiveTo": "2300-01-01T00:00:00",
"cciGeoId": 888,
"cciIsDisabled": 0,
"cciPraEmpId": 40336,
"cciTdEmpId": 14694,
"cciDescription": "South Bigtown",
"cciPostsummFlag": "S",
"cciCcFinancialLevel": 1,
"emiNameFirstPra": "Phil",
"emiNameFamilyPra": "Franklin",
"emiActiveToPra": "2300-01-01T00:00:00",
"emiEmailAddressPra": "Phil.Franklin#example.com",
"emiNameFirstTd": "Phillipa",
"emiNameFamilyTd": "Howard",
"emiActiveToTd": "2300-01-01T00:00:00",
"emiEmailAddressTd": "Phillipa.Howard#example.com"
}
]

OK I found the answer to this.
I simply passed the response from the Ajax straight back rather than trying to build an array out of it. So the testFindParents code now looks like this :
testFindParents: function () {
var result = [];
return new Ember.RSVP.Promise(function (resolve, reject) {
const theDrvId = 888;
const theClientCode = 'ABC';
const theCceIdentifier = 'XYZXY';
var theUrl = "api/parentcostcentres/" + theDrvId + "/" + theClientCode + "/" + theCceIdentifier ;
Ember.$.ajax({
type: 'GET',
url: theUrl,
success: function (data) {
resolve(data);
},
error: function (request, textStatus, error) {
console.log(error);
reject(error);
}
});
});
},
Of course that doesn't explain why I can't instantiate an instance of parentcostcentre as I was trying to in the test code but the primary problem at least is resolved.

Related

How can I handle a ajax request response in the Flux Architecture?

Looking at the Flux Documentation I can't figure out how the code to a ajax update, and a ajax fetch would fit into the dispatcher, store, component architecture.
Can anyone provide a simple, dummy example, of how an entity of data would be fetched from the server AFTER page load, and how this entity would be pushed to the server at a later date. How would the "complete" or "error" status of request be translated and treated by the views/components? How would a store wait for the ajax request to wait? :-?
Is this what you are looking for?
http://facebook.github.io/react/tips/initial-ajax.html
you can also implement a fetch in the store in order to manage the information.
Here is an example (it is a concept, not actually working code):
'use strict';
var React = require('react');
var Constants = require('constants');
var merge = require('react/lib/merge'); //This must be replaced for assign
var EventEmitter = require('events').EventEmitter;
var Dispatcher = require('dispatcher');
var CHANGE_EVENT = "change";
var data = {};
var message = "";
function _fetch () {
message = "Fetching data";
$.ajax({
type: 'GET',
url: 'Url',
contentType: 'application/json',
success: function(data){
message = "";
MyStore.emitChange();
},
error: function(error){
message = error;
MyStore.emitChange();
}
});
};
function _post (myData) {
//Make post
$.ajax({
type: 'POST',
url: 'Url',
// post payload:
data: JSON.stringify(myData),
contentType: 'application/json',
success: function(data){
message = "";
MyStore.emitChange();
},
error: function(error){
message = "update failed";
MyStore.emitChange();
}
});
};
var MyStore = merge(EventEmitter.prototype, {
emitChange: function () {
this.emit(CHANGE_EVENT);
},
addChangeListener: function (callback) {
this.on(CHANGE_EVENT, callback);
},
removeChangeListener: function (callback) {
this.removeListener(CHANGE_EVENT, callback);
},
getData: function (){
if(!data){
_fetch();
}
return data;
},
getMessage: function (){
return message;
},
dispatcherIndex: Dispatcher.register( function(payload) {
var action = payload.action; // this is our action from handleViewAction
switch(action.actionType){
case Constants.UPDATE:
message = "updating...";
_post(payload.action.data);
break;
}
MyStore.emitChange();
return true;
})
});
module.exports = MyStore;
Then you need to subscribe your component to the store change events
var React = require('react');
var MyStore = require('my-store');
function getComments (){
return {
message: null,
data: MyStore.getData()
}
};
var AlbumComments = module.exports = React.createClass({
getInitialState: function() {
return getData();
},
componentWillMount: function(){
MyStore.addChangeListener(this._onChange);
},
componentWillUnmount: function(){
MyStore.removeChangeListener(this._onChange);
},
_onChange: function(){
var msg = MyStore.getMessage();
if (!message){
this.setState(getData());
} else {
this.setState({
message: msg,
data: null
});
}
},
render: function() {
console.log('render');
return (
<div>
{ this.state.message }
{this.state.data.map(function(item){
return <div>{ item }</div>
})}
</div>
);
}
});
I hope it is clear enough.

Removing a subdoc using AJAX & Mongoose

How do you properly delete a subdoc (a task in this case) with AJAX in Mongoose?
Everything seems to be working up until the ajax in the file that's loaded into the page. Or could the problem be in the controller? I have read that you can't perform a .remove on a child element and I'm unclear on how to handle a delete.
Here is the schema:
//new user model
var mongoose = require('mongoose');
var Schema = mongoose.Schema;
var ObjectId = Schema.ObjectId;
// Task schema
var taskSchema = mongoose.Schema({
clientEasyTask : { type: String },
clientHardTask : { type: String },
clientStupidTask : { type: String }
});
var userSchema = new mongoose.Schema({
email: { type: String, unique: true, lowercase: true },
password: String,
task : [taskSchema]
});
module.exports = mongoose.model('Task', taskSchema);
module.exports = mongoose.model('User', userSchema);
The JS loaded into the page:
// Delete
$(document).ready(function() {
console.log('called del function');
var $alert = $('.alert');
$alert.hide();
$alert.on('error', function(event, data){
$alert.html(data)
$alert.addClass('alert-danger');
$alert.show();
});
$alert.on('success', function(event, data) {
$alert.html(data);
$alert.addClass('alert-info');
$alert.show();
})
$('.task-delete').click(function(event) {
console.log('click event occurred');
$target = $(event.target)
$.ajax({
type: 'DELETE',
url: apiDeleteTask + $target.attr('data-task-id'),
success: function(response) {
$target.parent.children.id(id).remove();
$alert.trigger('success', 'Task was removed.');
},
error: function(error) {
$alert.trigger('error', error);
}
})
});
})
Routes, which matches the working update route:
var tasks = require('./controllers/tasks-controller'),
var User = require('./models/user');
var Task = require('./models/user');
module.exports = function (app, passport) {
// Delete Task
app.delete('/api/tasks/:id', tasks.del);
};
And the tasks-controller.js
var User = require('../models/user');
var Task = require('../models/user');
exports.del = function(req, res, next) {
return User.update({ 'task._id': req.params.id }, { $set: { 'task.$.clientEasyTask': req.body.clientEasyTask }},
(function(err, user) {
if(!user) {
res.statusCode = 404;
return res.send({ error: 'Not phound' });
}
if(!err) {
console.log("Updated Existing Task with ID: " + req.params.id + " to read: " + req.body.clientEasyTask ),
res.redirect('/dashboard');
} else {
res.statusCode = 500;
console.log('Internal error(%d): %s', res.statusCode, err.message);
return res.send({ error: 'Server error' });
}
})
);
};
And last but not least I'm getting this error, that gives the task_id string & line 0:
[Error] Failed to load resource: the server responded with a status of 404 (Not Found) (54c55ac0443873db1eb8c00c, line 0)
In order to remove an entire field from the child array (tasks) the solution is to use $unset. I was wanting to use $set to update the field with a null value, but this is exactly what $unset does.
Here is the line in question that now works:
return User.update({ 'task._id': req.params.id }, { $unset: { 'task.$.clientEasyTask': req.body.clientEasyTask }},
Read more about field operators here: http://docs.mongodb.org/manual/reference/operator/update-field/
$pull would work if you want to remove the array elements without leaving behind a null value, but you must have a specific, matching query. Read about $pull and other array update options here:
http://docs.mongodb.org/manual/reference/operator/update-array/
Also, if you are struggling with a problem I can't stress how important it is to read the documentation. I can guarantee you that everyone on here that is answering problems is doing this, or has learned from someone who does.
Do the work. You'll figure it out. Don't give up.

Unknown provider: $angularCacheFactoryProvider - angular-cache can not be found

I am trying to implement angular-cache in my app. I have downloaded it and include a tag in html
However I keep getting the error: Error: [$injector:unpr] Unknown provider: $angularCacheFactoryProvider <- $angularCacheFactory
I'd appreciate some help
My code is the following:
controllers.js
.controller('PlaylistsCtrl', ['$scope', '$angularCacheFactory', 'myService', '$http', '$rootScope', 'Util', '$location', function ($scope, $angularCacheFactory, myService, $http, $rootScope, Util, $location) {
$rootScope.allDeals = [];
$scope.navigate = function(url){
$location.path(url);
};
myService.getDataById(1)
.then(function (data) {
// e.g. "time taken for request: 2375ms"
// Data returned by this next call is already cached.
myService.getDataById(1)
.then(function (data) {
// e.g. "time taken for request: 1ms"
});
});
}])
services.js
.service('myService',['$http', '$q', '$rootScope', '$angularCacheFactory', function ($http, $q, $rootScope, $angularCacheFactory) {
$rootScope.allDeals = [];
$angularCacheFactory('dataCache', {
maxAge: 900000,
// Items will be actively deleted when they expire
deleteOnExpire: 'aggressive',
// This cache will clear itself every hour
cacheFlushInterval: 3600000
});
return {
getDataById: function (id) {
var deferred = $q.defer(),
start = new Date().getTime();
$http.get('http://dev.somecompany.net/bigcapi/info/info/someinfo' + id, {
params: {all: '1', mobileready: 1},
cache: $angularCacheFactory.get('dataCache')
}).success(function (data) {
$rootScope.allDeals = data;
console.log('time taken for request: ' + (new Date().getTime() - start) + 'ms');
deferred.resolve(data);
});
return deferred.promise;
}
};
}])
U forgot to include angular-cache module dependency

How to access the JSON on HTTP from an HTTPS page?

Here is my code I am trying to access the content on HTTP page from an HTTPS page it is giving me an error in browser console that it is an insecure content, following is an error ' Loading mixed (insecure) active content on a secure page "http://pnrbuddy.com/api/station_by_code/code/cnb/format/json/pbapikey/539ff0f815ca697c681fe01d32ba52e3/pbapisign/906544ca31f9c0048e80bde8127556af828e313b" ' , it is showing Json inbrowser console but unable to read it. How can I read that JSON?
'use strict';
var context = SP.ClientContext.get_current();
var user = context.get_web().get_currentUser();
(function () {
// This code runs when the DOM is ready and creates a context object which is
// needed to use the SharePoint object model
$(document).ready(function ()
{
getUserName();
$("#button1").click(function()
{
paraupdate();
});
});
// This function prepares, loads, and then executes a SharePoint query to get
// the current users information
function paraupdate()
{
var str=""+$("#textbox1").val();
alert(""+str);
var message = str+"json539ff0f815ca697c681fe01d32ba52e3";
var secret = "<my private key>";
var crypto = CryptoJS.HmacSHA1(message, secret).toString();
alert("crypto answer is " + crypto);
var siteurl="http://pnrbuddy.com/api/station_by_code/code/"+str+"/format/json/pbapikey/539ff0f815ca697c681fe01d32ba52e3/pbapisign/"+crypto;
//////////////////////////////////////////////
$.ajax({
url: siteurl,
type: "GET",
dataType: 'json',
/* headers: {
"accept": "application/json;odata=verbose",
}, */
success: function (data) {
alert("Success");
alert(data.Station);
/* $.each(data.d.results, function (index, item)
{
alert("My ID"+index);
alert("Item"+item);
});
//var str=JSON.parse(data);
var myResults = [];
$.each(data, function (index, item) {
alert("dsfsd"+item.station_by_code)
myResults.push({
id: item.id,
//text: item.first_name + " " + item.last_name
});
}); */
},
error: function (error) {
alert("IN Error");
alert(JSON.stringify(error));
}
});
/////////////////////////////////////////////
}
function getUserName()
{
context.load(user);
context.executeQueryAsync(onGetUserNameSuccess, onGetUserNameFail);
}
// This function is executed if the above call is successful
// It replaces the contents of the 'message' element with the user name
function onGetUserNameSuccess()
{
$("#label1").html("Enter Station Code : ");
$("#button1").val("CLICK");
}
// This function is executed if the above call fails
function onGetUserNameFail(sender, args) {
alert('Failed to get user name. Error:' + args.get_message());
}
})();
'use strict';
var context = SP.ClientContext.get_current();
var user = context.get_web().get_currentUser();
(function () {
// This code runs when the DOM is ready and creates a context object which is
// needed to use the SharePoint object model
$(document).ready(function ()
{
getUserName();
$("#button1").click(function()
{
paraupdate();
});
});
// This function prepares, loads, and then executes a SharePoint query to get
// the current users information
function paraupdate()
{
var str=""+$("#textbox1").val();
alert(""+str);
var message = str+"json539ff0f815ca697c681fe01d32ba52e3";
var secret = "<my private key>";
var crypto = CryptoJS.HmacSHA1(message, secret).toString();
alert("crypto answer is " + crypto);
var siteurl="http://pnrbuddy.com/api/station_by_code/code/"+str+"/format/json/pbapikey/539ff0f815ca697c681fe01d32ba52e3/pbapisign/"+crypto;
//////////////////////////////////////////////
$.ajax({
url: siteurl,
type: "GET",
dataType: 'json',
success: function (data) {
alert("Success");
alert(" Code : "data.stations[0].code+" Name : "+data.stations[0].name);
},
error: function (error) {
alert("IN Error");
alert(JSON.stringify(error));
}
});
/////////////////////////////////////////////
}
function getUserName()
{
context.load(user);
context.executeQueryAsync(onGetUserNameSuccess, onGetUserNameFail);
}
// This function is executed if the above call is successful
// It replaces the contents of the 'message' element with the user name
function onGetUserNameSuccess()
{
$("#label1").html("Enter Station Code : ");
$("#button1").val("CLICK");
}
// This function is executed if the above call fails
function onGetUserNameFail(sender, args) {
alert('Failed to get user name. Error:' + args.get_message());
}
})();

MVC3 and Twitter Bootstrap TypeAhead without plugin

I have gotten TypeAhead to work properly with static data and am able to call my controller function properly and get data but it is either A: Not parsing the data properly or B: The TypeAhead is not set up correctly.
JavaScript :
<input type="text" id="itemSearch" data-provide="typeahead" value="#ViewBag.Item" name="itemSearch"/>
$('#itemSearch').typeahead({
source: function (query, process) {
parts = [];
map = {};
$.ajax({
url: '#Url.Action("MakePartsArray")',
dataType: "json",
type: "POST",
data: {query: query},
success: function (data) {
$.each(data, function (i, part) {
map[part.description] = part;
parts.push(part.description);
});
typeahead.process(parts);
}
});
},
updater: function (item) {
selectedPart = map[item].itemNumber;
return item;
},
matcher: function (item) {
if (item.toLowerCase().indexOf(this.query.trim().toLowerCase()) != -1) {
return true;
}
},
sorter: function (items) {
return items.sort();
},
highlighter: function (item) {
var regex = new RegExp('(' + this.query + ')', 'gi');
return item.replace(regex, "<strong>$1</strong>");
}
});
Controller :
public ActionResult MakePartsArray(string query)
{
var possibleItem = query.ToLower();
var allItems = Db.PartInventorys.Where(l => l.ItemNumber.Contains(possibleItem)).Select(x => new { itemNumber = x.ItemNumber, description = x.Description });
return new JsonResult
{
ContentType = "text/plain",
Data = new { query, total = allItems.Count(), suggestions = allItems.Select(p => p.itemNumber).ToArray(), matches = allItems, },
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};
}
In my controller I see the data being retrieved correctly and it appears to parse properly but nothing is showing up for my TypeAhead.
Any idea on how to verify exactly where the breakdown is occurring or does anyone see direct fault in my code?
Problem was in the ajax call-
$.ajax({
url: '#Url.Action("MakePartsArray")',
dataType: "json",
type: "POST",
data: {query: query},
success: function (data) {
$.each(data.matches, function (i, part) {
var composedInfo = part.description + ' (' + part.itemNumber + ')';
map[composedInfo] = part;
parts.push(composedInfo);
});
process(parts);
}
});
and in the controller on the return type
return new JsonResult
{
ContentType = "application/json",
Data = new { query, total = allItems.Count(), suggestions = allItems.Select(p => p.itemNumber).ToArray(), matches = allItems },
JsonRequestBehavior = JsonRequestBehavior.AllowGet
};

Resources