Sencha Touch: REST store and DELETE request - rest

I'm new to Sencha Touch and I'm having problems to delete a record.
This is my model:
Ext.define('MyApp.model.Customer', {
extend: 'Ext.data.Model',
...
config: {
idProperty: 'key',
fields: [
{
name: 'key',
type: 'auto'
},
{
name: 'name',
type: 'string'
}
...
]
}
....
}
and this is an event associated with a delete customer button:
onDeleteCustomerBtnTap: function(button, e, eOpts) {
var data = this.getCustomerDetail().getData();
var store = Ext.getStore("CustomerStore");
var record = store.getById(data.key);
store.remove(record);
store.sync();
}
EDIT:
this is the store
proxy: {
type: 'rest',
url: 'http://example.com/customers',
useDefaultXhrHeader: false,
appendId: false,
reader: {
type: 'json',
idProperty: 'key',
rootProperty: 'data'
},
writer: {
type: 'json'
}
}
The problem is when it tries to sync the store. The request url is http://example.com/customers?_dc=1394840324234 instead of http://example.com/customers/10?_dc=1394840324234.
What am I doing wrong?

I finally used the erase method of Ext.data.Model. Here is my final version:
var data = this.getCustomerDetail().getData();
var store = Ext.getStore("CustomerStore");
var record = store.getById(data.key);
record.erase({
success: function() {
// ...
}
}
});

are you defining your proxy as 'rest' and not 'ajax'?
proxy: {
type: 'rest',
url : '/users'
}

Related

Vuejs drag sort items and save to mongoDB with Axios

I am beginner and my goal is to fetch items from DB, drag and sort them, and then save that sorted list in my DB. I have managed to fetch and set up drag sort vuejs component and I get key pair values of sorted items, but I don't know hot to save it to db.
When I execute saveNewSequence, I get console log value from forEach and nothing else, but when I refresh my page I get error: request aborted. And my list is not updated in DB.... I believe I have to somehow connect key value with id... can you please help.
Vue component:
data() {
return {
ropes: [],
}
},
methods:{
saveNewSequence() {
this.ropes.forEach((rope, key)=>{
console.log('Key' + key +' '+ rope._id)
})
let postData = {}
postData.ropes = this.ropes.map(rope=>{
return{
title: rope.title,
description:rope.description,
image: rope.image,
price: rope.price,
cartQuantity: rope.cartQuantity
}
})
axios.post('https://zokadb.herokuapp.com/api/ropes', postData)
.then((res) => {
console.log(res)
}).catch(error => {
console.log(error)
})
},
}
this is my mongoDB model:
const ropeSchema = new mongoose.Schema({
title: {
type: String,
required: true,
},
description: {
type: String,
required: true,
},
image: {
type: String,
required: false,
},
price: {
type: Number,
required: true,
},
cartQuantity: {
type: Number,
required: true,
},
date: {
type: Date,
default: Date.now
}
})
Try :
postData = this.ropes.map(rope=>{
...
instead of :
postData.ropes = this.ropes.map(rope=>{
...
if you want to send post request with postData:
axios.post('https://zokadb.herokuapp.com/api/ropes', postData)
...

UUID as primary key in sailsjs domain

I am using Sails.js version 1.0.2. I am trying to assign uuid as primary key throughout the application. I tried putting
id: { type: 'string', defaultsTo:uuid.v4() } in model.js but it's saying Primary keys must be unique therefore can't contain a default value.
_________________EDIT_______________
I tried this code in my domain
beforeCreate: function (modelObj, next) {
modelObj.id = uuidv4.v4();
next();
}
And edit my Model.js configuration is like :
attributes: {
createdAt: { type: 'number', autoCreatedAt: true, },
updatedAt: { type: 'number', autoUpdatedAt: true, },
id: { type: 'string',required:true},
}
beforeCreate method never executes and throw the error while creating the record like:
error: Sending 500 ("Server Error") response:
{ UsageError: Invalid new record.
Details:
Missing value for required attribute `id`. Expected a string, but
instead, got: undefined
Please let me know if I am doing anything wrong.
Thanks
You can do something like this instead of giving default value
beforeCreate: function (modelObj, next) {
modelObj.id = uuid.v4();
next();
}
You can add this piece of function in your model. This gets invoked whenever there is a create operation on model.
Your Model.js should looks something like this
attributes: {
createdAt: { type: 'number', autoCreatedAt: true, },
updatedAt: { type: 'number', autoUpdatedAt: true, },
id: { type: 'string',required:true},
},
beforeCreate: function (modelObj, next) {
modelObj.id = uuid.v4();
next();
}
Sample code of my Controller and Model,
TestController.js
module.exports = {
create: function(req, res) {
Test.create({"name": "arshad"})
.then(function(result){
res.send("done");
})
}
};
Test.js Model
module.exports = {
attributes: {
id: { type: 'string', required: true },
name: { type: 'string' }
},
beforeCreate: function(obj, next) {
obj.id = 'someId';
next();
}
};
This is how your model and controller will look like. This will add someId as defined in beforeCreate function to the object
In your case you are using uuid package. Check in debugging mode whether uuid reference is available in beforeCreate or not

JqxScheduler Customization dialog

I want to customize the dialog box in jqx scheduler dialog box title. Instead of 'Create new appointment' i want to display "Create a new business schedule".
I work with python django so in the code there are some elements from django template code. So far i create , edit, delete appointments with ajax and django as backend.
var items;
function setAvailability(price_data,persons_data,start_date,end_date, id, a_type, description){
availability_data = {
pk : "{{form.instance.pk}}",
csrfmiddlewaretoken: "{{ csrf_token }}",
price:price_data,
persons:persons_data,
from_date:start_date,
to_date:end_date,
a_type_data:a_type,
av_description:description
}
if(id) {
availability_data['event'] = id;
}
$.ajax({
url: "{% url 'set-availability' %}",
method: "POST",
data: availability_data,
dataType: "json",
success: function(response){
var source = {
datatype: "json",
dataFields: [
{ name: 'id', type: 'integer' },
{ name: 'description', type: 'string' },
{ name: 'location', type: 'string' },
{ name: 'status', type: 'string' },
{ name: 'price', type: 'number' },
{ name: 'persons', type: 'number' },
{ name: 'subject', type: 'integer' },
{ name: 'start', type: 'date', format: "yyyy-MM-dd"},
{ name: 'end', type: 'date', format: "yyyy-MM-dd"}
],
id: 'id',
url: "{% url 'get-availability' %}?pk={{form.instance.pk}}"
};
var adapter = new $.jqx.dataAdapter(source);
$("#scheduler").jqxScheduler({
source: adapter
})
return response;
}
})
}
$.ajax({
url: "{% url 'get-availability' %}",
method: "GET",
data: { pk : "{{form.instance.pk}}" },
dataType: "json",
success: function(response){
items = response;
var source = {
datatype: "array",
dataFields: [
{ name: 'id', type: 'integer' },
{ name: 'description', type: 'string' },
{ name: 'location', type: 'string' },
{ name: 'status', type: 'string' },
{ name: 'price', type: 'number' },
{ name: 'persons', type: 'number' },
{ name: 'subject', type: 'integer' },
{ name: 'start', type: 'date', format: "yyyy-MM-dd"},
{ name: 'end', type: 'date', format: "yyyy-MM-dd"}
],
id: 'id',
localData: items
};
var adapter = new $.jqx.dataAdapter(source);
$("#scheduler").jqxScheduler({
date: new $.jqx.date(2018, 02, 01),
width: 850,
height: 600,
source: adapter,
editDialogDateTimeFormatString: 'yyyy-MM-dd',
editDialogDateFormatString: 'yyyy-MM-dd',
showLegend: false,
localization: { editDialogStatuses: {
available: "Available",
booked: "Booked"
}},
renderAppointment: function(data)
{
if (data.appointment.status == "available") {
data.style = "#B8E6A3";
}
else if (data.appointment.status == "booked") {
data.style = "#FF0013";
}
return data;
},
ready: function () {
$("#scheduler").jqxScheduler('ensureAppointmentVisible', 'id1');
},
resources:
{
colorScheme: "scheme05",
dataField: "id",
source: new $.jqx.dataAdapter(source)
},
appointmentDataFields:
{
id: "id",
description: "description",
location: "location",
subject: "subject",
price: "price",
persons: "persons",
status: "status",
calendar: 'calendar',
from: "start",
to: "end",
},
view: 'monthView',
views:
[
'monthView'
],
renderAppointment: function (dialog, fields, renderAppointment) {
console.info('render appointment:', dialog);
},
editDialogCreate: function (dialog, fields, editAppointment) {
fields.repeatContainer.hide();
fields.subjectContainer.hide();
fields.timeZoneContainer.hide();
fields.colorContainer.hide();
fields.resourceContainer.hide();
fields.allDayContainer.hide();
fields.locationContainer.hide();
fields.fromContainer.hide();
fields.toContainer.hide();
fields.fromLabel.html("Start");
fields.toLabel.html("End");
var priceField = ''
var personsField = ""
priceField += "<div>"
priceField += "<div class='jqx-scheduler-edit-dialog-label'>Price</div>"
priceField += "<div class='jqx-scheduler-edit-dialog-field'><input type='number' id='price' step='0.01' /></div>"
priceField += "</div>"
personsField += "<div>"
personsField += "<div class='jqx-scheduler-edit-dialog-label'>Persons</div>"
personsField += "<div class='jqx-scheduler-edit-dialog-field'><input type='number' id='persons' /></div>"
personsField += "</div>"
var i = 0;
$('#dialogscheduler').children('div').each(function () { // loop trough the div's (only first level childs) elements in dialogscheduler
i += 1;
if (i == 2) { // places the field in the third position.
$(this).after(priceField);
$(this).after(personsField);
};
});
},
editDialogOpen: function (dialog, fields, editAppointment) {
console.info(dialog);
fields.repeatContainer.hide();
}
});
$('#scheduler').on('editDialogOpen', function (event) {
var args = event.args;
var appointment = args.appointment;
if(appointment){
$('#dialogscheduler > div').find('#price').val(appointment.price);
$('#dialogscheduler > div').find('#persons').val(appointment.persons);
}
else {
$('#dialogscheduler > div').find('#price').val(0);
$('#dialogscheduler > div').find('#persons').val(0);
$('#dialogscheduler > div').find('#from').val('');
$('#dialogscheduler > div').find('#to').val('');
$('#dialogscheduler > div').find('#description').val('');
$('#dialogscheduler > div').find('#status').val();
}
});
$('#scheduler').on('appointmentAdd', function (event) {
var price_data = $('#dialogscheduler > div').find('#price').val();
var persons_data = $('#dialogscheduler > div').find('#persons').val();
var a_type = event.args.appointment.status;
var description = event.args.appointment.description;
var start_date = event.args.appointment.from.toString();
var id = null;
var end_date = event.args.appointment.to.toString();
var availability = setAvailability(price_data,persons_data,start_date,end_date,id, a_type, description);
});
$('#scheduler').on('appointmentDelete', function (event) {
var id = event.args.appointment.id;
deleteEvent(id);
});
$('#scheduler').on('appointmentChange', function (event) {
var id = event.args.appointment.id;
var price_data = $('#dialogscheduler > div').find('#price').val();
var persons_data = $('#dialogscheduler > div').find('#persons').val();
var description = event.args.appointment.description;
var a_type = event.args.appointment.status;
var start_date = event.args.appointment.from.toString();
alert(start_date);
var end_date = event.args.appointment.to.toString();
var availability = setAvailability(price_data,persons_data,start_date,end_date,id, a_type,description);
});
}
})
function deleteEvent(pk) {
$.ajax({
url: "{% url 'delete-availability' %}",
method: "GET",
data: { pk : pk, business_pk:'{{form.instance.pk}}'},
dataType: "json",
success: function(response){
console.info(response)
}
})
}
I think you need to put the below code snippet in the editDialogOpen() function. This is working for me.
setTimeout(function() {
dialogRef.find("div").first().find("div").first().html("Create a new business schedule");
}, 10);
You can use the localization to do it. I'm using jqxScheduler with Angular, so:
Add [localization]="localization" into the component definition that should looks like:
<jqxScheduler #scheduler [editDialogCreate]="editDialogCreate" [localization]="localization">
Add a localization property into the component class. jqxScheduler has different titles for create and edit appointents:
localization = {
editDialogTitleString: 'Edit a business schedule',
editDialogCreateTitleString: 'Create a new business schedule'
};
jQWidgets has implementation examples to other languages. JQuery here.
$("#scheduler").jqxScheduler({
localization: {
editDialogCreateTitleString: "Create a new business schedule",
},
});

Get slug from object in view won't work

I have created a new object named Project, that contains a gallery and some other fields in it. In the view, I'm showing some data from it and I want to put a link to previous and next project. I already managed to get the previous project but when I try to get the slug from it, somehow it doesn't work.
This is the Project model:
var keystone = require('keystone');
var Types = keystone.Field.Types;
/**
* Project Model
* ==========
*/
var Project = new keystone.List('Project', {
map: { name: 'title' },
autokey: { path: 'slug', from: 'title', unique: true }
});
Project.add({
title: { type: String, required: true },
state: { type: Types.Select, options: 'draft, published, archived', default: 'draft', index: true },
author: { type: Types.Relationship, ref: 'User', index: true },
publishedDate: { type: Types.Date, index: true, dependsOn: { state: 'published' } },
category: { type: String, required: false },
description: { type: Types.Html, wysiwyg: true, height: 150 },
shortDescription: { type: Types.Html, wysiwyg: true, height: 100 },
credits: { type: Types.Html, wysiwyg: true, height: 100 },
galleries: { type: Types.Relationship, ref: 'Gallery', many: false },
color: { type: String, required: false }
});
Project.schema.virtual('content.full').get(function() {
return this.content.extended || this.content.brief;
});
Project.defaultColumns = 'title, state|20%, author|20%, publishedDate|20%';
Project.register();
This is the controller:
var keystone = require('keystone');
exports = module.exports = function(req, res) {
var view = new keystone.View(req, res);
var locals = res.locals;
// Set locals
locals.section = 'projects';
locals.filters = {
project: req.params.project
};
locals.data = {
projects: [],
previousProject: []
};
// Load the current project
view.on('init', function(next) {
var q = keystone.list('Project').model.findOne({
state: 'published',
slug: locals.filters.project
}).populate('galleries');
q.exec(function(err, result) {
locals.data.project = result;
next(err);
});
});
//Load other projects
view.on('init', function(next) {
var q = keystone.list('Project').model.find({state: "published", publishedDate: {$lt: locals.data.project.publishedDate}}).sort('-publishedDate').limit(1);
q.exec(function(err, results) {
locals.data.previousProject = results;
next(err);
});
});
// Render the view
view.render('project');
};
And this is the view:
<div class="container">
<p>{{{data.project.title}}}</p>
<p>—</p>
<p>{{{data.project.category}}}</p>
{{#if data.project.galleries}}
{{#each data.project.galleries.images}}
<img src="{{url}}" />
{{/each}}
{{/if}}
<p>full project: {{data.previousProject}}</p>
<p>slug: {{data.previousProject.slug}}</p>
{{#if data.previousProject}}
<a href="/projects/{{data.previousProject.slug}}" >Previous project</a>
{{/if}}
</div>
Somehow, {{data.previousProject}} shows the correct record info but when I do {{data.previousProject.slug}} it returns nothing at all. I've been scratching my head against this for hours but I can't find where is the issue. Thanks in advance!!
I finally found what the issue was: in the controller I'm using model.find whereas I should be using model.findOne if I know I only need one record and I want to directly get the values from it with .slug. Using limit(1) was not enough.

Waterline, error when trying to create one-to-many association

I have these models:
// Material.js
module.exports = {
attributes: {
name: {
type: 'string',
required: true
},
source_info: {
type: 'string',
required: true
},
category: { model: 'category_mat' }
}
};
and:
// Category_Mat.js
module.exports = {
attributes: {
name: {
type: 'string',
required: true
},
material:{
collection: 'material',
via: 'category'
}
},
};
but when I run the app I get this error:
/usr/local/lib/node_modules/sails/node_modules/waterline/node_modules/waterline-schema/lib/waterline-schema/foreignKeys.js:82
throw new Error('Trying to access a collection ' + collection + ' that is
^
Error: Trying to access a collection category_mat that is not defined.
at ForeignKeys.findPrimaryKey (/usr/local/lib/node_modules/sails/node_modules/waterline/node_modules/waterline-schema/lib/waterline-schema/foreignKeys.js:82:11)
at ForeignKeys.replaceKeys (/usr/local/lib/node_modules/sails/node_modules/waterline/node_modules/waterline-schema/lib/waterline-schema/foreignKeys.js:53:27)
at new ForeignKeys (/usr/local/lib/node_modules/sails/node_modules/waterline/node_modules/waterline-schema/lib/waterline-schema/foreignKeys.js:30:10)
at new module.exports (/usr/local/lib/node_modules/sails/node_modules/waterline/node_modules/waterline-schema/lib/waterline-schema.js:30:17)
at Waterline.initialize (/usr/local/lib/node_modules/sails/node_modules/waterline/lib/waterline.js:106:17)
at buildORM (/usr/local/lib/node_modules/sails/lib/hooks/orm/build-orm.js:48:15)
at Array.async.auto.instantiatedCollections [as 1] (/usr/local/lib/node_modules/sails/lib/hooks/orm/index.js:191:11)
at listener (/usr/local/lib/node_modules/sails/node_modules/async/lib/async.js:465:46)
at /usr/local/lib/node_modules/sails/node_modules/async/lib/async.js:419:17
at Array.forEach (native)
I used this documentation as reference:
http://sailsjs.org/#/documentation/concepts/ORM/Associations/OnetoMany.html
so I don't know what I'm missing or if there is a configuration that I have to do... any help?
Maybe it is because "category-mat" used on Material.js is not defined anywhere... try
// Category_Mat.js
module.exports = {
identity: 'category_mat',
attributes: {
name: {
type: 'string',
required: true
},
material:{
collection: 'material',
via: 'category'
}
},
};
If this works the only side effect is that even if you have config/globals.js/models set to "true", you won't be able to access the model in the controllers by using "Category_Mat". You will either have to use "sails.models.category_mat" or just "category_mat".