Submit формы используя REST API
Всем привет!
Сделал REST ресурс и нарисовал к нему грид и форму редактирования. Создаю окно редактирования и добавления так:
this.dialog = main.add({
xtype: 'employees-window',
viewModel: {
data: {
title: record ? 'Редактирование: ' + record.get('id') : 'Добавить сотрудника'
},
links: {
theEmployee: record || {
type: 'MyApp.model.employees.Employees',
create: true
}
}
},
});
Сама модель помимо объявления полей содержит вот такое объявление прокси (в store код такой же):
proxy: {
type: 'api',
url: MyApp.Global.getApiUrl() + 'api/v1/employees'
}
В общем, окошко функционирует нормально, выдает пустые поля для добавления и заполняет значения при редактировании. Но возникла проблема уже на этапе добавления записи. Такой код:
onSaveClick: function () {
//get form
var form = this.lookupReference('form');
if (form.isValid()) {
form.submit();
}
}
Выдает ошибку `No URL specified`. Пока поиск мало информации дал... одни пишут форму сабмитить надо, другие то что с моделью работать через `model.save()`, третьи про ViewModel предлагают... пока никаких результатов у меня. Так как правильно то добавлять и обновлять записи в store? |
В общем, выкрутился вот так:
var store = Ext.getStore('employees1');
store.insert(0, this.getViewModel().data.theEmployee);
store.reload();
Что интересно, если выводишь в таблице id, то вместо него выдает мне название класса с цифрой на конце, например, `employees.Employees-7`. `reload()` перезагружает store уже нормально, хотелось бы понять как id предварительно получить... в примерах это есть, но для раздельных сессий. |
Я сделал базовый клас для формы с кнопками "Сохранить" и "Отменить"
На сохранить навесил примерно такой код: var record = form.getRecord(); record.save() А на отмену закрытие окна(сделал у формы modal:true) формы. Далее при необходимости редактирования какой либо модели. Создаю новую форму - наследника от базовой. Она содержит только поля формы. Далее form.setRecord(экземпляр модели) Очень удобно получилось. Работает уже для кучи моделей. И как правило базового функционала хватает. Еще у меня форма при клике сохранить вызывает событие save. на него подписывается контроллер который создал форму. И по сохранению записи и закрытии форму он например обновляет дерево или каконибудь грид. |
Про Id.
Если экземпляр модели новый то id по умолчанию именно такой. Если это экземпляр из грида то у него по логике уже есть id. и он должен сохранится при setRecord/getRecord |
Цитата:
Кстати, у вас проверяется правильность ответа сервера? А то вот у меня была ошибка в server-side коде, а при этом в store запись вставилась и в Grid'е отобразилась :blink: Все это до перезагрузки страницы. Цитата:
Цитата:
|
А каким образом обновлять запись в store? Не удалять, не вставлять, а именно обновлять...
Не нашел метода update в документации, а мне необходимо именно обновление записи. Если я пишу вот так: dialog.getViewModel().data.theEmployee.save(); то событие write у Store попросту не срабатывает, хотя вызов PUT метода в REST происходит и запись обновляется! p.s. Если попытаться обновить запись вставкой, вот так: store.insert(index, dialog.getViewModel().data.theEmployee); То сначала сработает необходимый нам PUT с изменениями... и тут же сразу DELETE этой записи. В итоге запись удаляется :blink: |
Такая базовая форма:
Ext.define('common.helpers.BaseForm', {
extend: 'Ext.form.Panel',
alias: 'helpers.baseform',
controller:{
type:'helpers.baseformcontroller'
},
modal:true,
frame: true,
closable:true,
floating:true,
reference: 'form',
buttons: [
{
formBind: true,
disabled: true,
text:'Сохранить',
handler:'save'
},
{
text: 'Отменить',
handler: function(){
this.up('form').close();
}
}
]
});
Её контроллер:
Ext.define('KSoft.common.helpers.BaseFormController', {
extend: 'Ext.app.ViewController',
alias: 'controller.ksoft.helpers.baseformcontroller',
save:function(){
var me = this,
form = this.view,
record = form.getRecord();
if (form.isValid()) {
form.updateRecord(record);
if(form.extraParams != undefined)
record.proxy.setExtraParams(form.extraParams);
record.save({
success: function(record, operation) {
form.fireEvent('save', form); //--- Тут вызываем событие о том что запись успешно сохранена
form.close();
},
failure: function(record, operation) {
//Тут обрабатываем ошибку сохранения.
}
});
} else {
Ext.Msg.alert('Некорректные данные', 'Введите корректные данные');
}
}
});
Вот пример формы:
Ext.define('view.objects.ObjectForm', {
extend: 'view.helpers.BaseForm',
alias: 'objectform',
title:'Объект',
items: [
{
xtype: 'textfield',
fieldLabel: 'Name',
name: 'Name'
}
{
xtype: 'textfield',
fieldLabel: 'Code',
name: 'Code'
},
{
xtype: 'textfield',
fieldLabel: 'Icon Cls',
name: 'iconCls'
},
{
xtype: 'textfield',
fieldLabel: 'Long Name',
name: 'LongName'
},
{
xtype: 'textfield',
fieldLabel: 'Short Name',
name: 'ShortName'
},
{
xtype: 'numberfield',
fieldLabel: 'Number Name',
name: 'IntName'
},
{
xtype: 'checkboxfield',
fieldLabel: 'isActive',
name: 'Active',
checked: true,
uncheckedValue: false
},
{
xtype: 'hiddenfield',
name: 'ObjId'
}
]
});
Использую так: Например есть дерево объектов в котором можно добавлять или изменять объекты. Делается это при вызове соответствующих методов контроллера. В которых я уже вызываю непосредственно форму:
var form = new view.objects.ObjectForm;
form.loadRecord(object);
form.on('save',this.formSave, this);
form.show();
После сохранения формы я обновляю соответствующую ветку дерева. Кстати форма получилась универсальной. Например у меня есть грид в качестве модели которого модель из формы выше. Так я из него вызываю данную форму и меняю свойства модели и т.п. Окно поверх вьюпорта. так как создается с помощью new. По поводу обновления. Я обычно обновляю весь стор после обновления записи. Ну или конкретную ветку если это дерево. |
Цитата:
Личный опыт, один раз потратил несколько часов на отлов такого животного. Поймал только благодаря тому, что какой-то несчастный клиент вместе с ребятами из техподдержки бодались две недели и сузили набор вариантов до "в dev версии работает, в боевой сборке не работает". |
Да. Есть, такое.
Поправим. Этот костыль из прошлого вообще убрать нужно. Пытались к модели привязать дополнительные параметры которые не являются свойствами модели. Решили. а строчки остались. |
XAPuTOH, у вас и вставка новой записи отрабатывает через этот же код?
|
XAPuTOH, Сделал по примеру того как Вы написали. Вот код на редактирование:
onEdit: function(view, cell, rowIndex, colIndex, e, rec, row) {
console.log(rec);
var form = new MyApp.view.dictionaries.positions.PositionsForm({
viewModel: {
data: {
title: 'Редактирование'
}
}
});
console.log(form);
form.loadRecord(rec);
form.show();
},
Форма показывается, заполняется и даже отправляется куда надо, но при этом если мы жмем "Сохранить" без редактирования, то в request'е уходит лишь id! Т е получается у нас значения уходят на сервер лишь при изменении. Как Вы этот момент отлавливаете? Еще почему-то у меня два PUT'а на сервер уходят вместо 1го...я так понимаю, что тут проблема в том, что после updateRecord идет сразу record.save и получается 2 одинаковых действия. Если мы убираем record.save, то уже нет проблемы отправки пустой записи и форма просто закрывается на "Сохранить". Можете также выложить ф-цию `this.formSave`и объяснить момент со вставкой? :thanks: p.s. Этот код не сработает никогда:
} else {
Ext.Msg.alert('Некорректные данные', 'Введите корректные данные');
}
Потому что в форме прописано на кнопке "Сохранить" вот это: formBind: true, disabled: true, У пользователя нет никакой возможности нажать на кнопку, которая отключена =) |
В общем, унифицированной универсальной формы не получилось. Получилось некое её подобие. :-?
Дело в том, что мне вставка новой записи нужна именно через Store, иначе событие write, которое показывает всплывающие toast-сообщения, не отрабатывает. А к Store, который может быть любым, неизвестно каким образом вообще обращаться из этой формы. То, что `record.save()` не связано с обновлением хранилища писали еще тут: http://javascript.ru/forum/extjs/564...tml#post375259 Вот такая форма:
Ext.define('MyApp.view.helpers.Baseform', {
extend: 'Ext.form.Panel',
xtype: 'baseform',
controller: 'baseform',
bind: {
title: '{editformTitle}'
},
layout: {
type: 'vbox',
align: 'stretch'
},
bodyPadding: 10,
border: false,
width: 400,
modal: true,
closable: true,
closeToolText: 'Закрыть',
floating: true,
reference: 'form',
buttons: [
{
formBind: true,
disabled: true,
text:'Сохранить',
handler:'save'
},
{
text: 'Отменить',
handler: function(){
this.up('form').close();
}
}
]
});
Ее контроллер. Тут я проверяю id на целое число. Если целое, то у нас редактирование, если нет, то это новая запись. Также я сам record передаю при вызове события:
Ext.define('MyApp.view.helpers.BaseformController', {
extend: 'Ext.app.ViewController',
alias: 'controller.baseform',
save: function() {
var me = this,
form = this.view,
record = form.getRecord();
// console.log(record);
if (form.isValid()) {
var id = record.getId();
var values = form.getValues();
// console.log(values);
//check if edit
if (Ext.isNumber(id)) {
record.beginEdit();
record.set(values);
record.endEdit();
} else {
record.set(values);
form.fireEvent('insertNew', record);
}
form.close();
}
}
});
Обработчики добавления, редактирования и создания формы:
onAdd: function() {
console.log('onAdd');
var record = Ext.create('MyApp.model.dictionaries.positions.Positions');
console.log(record);
this.createForm(record, true);
},
onEdit: function(view, cell, rowIndex, colIndex, e, rec, row) {
this.createForm(rec, false);
},
createForm: function(record, stateNew) {
// console.log(record);
var form = new MyApp.view.dictionaries.positions.PositionsForm({
viewModel: {
data: {
editformTitle: stateNew ? 'Добавление' : 'Редактирование'
}
}
});
// console.log(form);
form.loadRecord(record);
form.on('insertNew', this.formInsertNew, this);
form.show();
},
А вот обработчик события вставки:
formInsertNew: function(record) {
console.log('NEW RECORD!!!!');
console.log(record);
var store = this.getView().getStore();
store.insert(0, record);
}
Обновляю я store в событии `write`, там же вывожу toast-сообщение. Да, есть неудобный костыль с обращением к store, но пока иного решения не нашел. Буду признателен, если кто-нибудь из форумчан даст ответы на эти вопросы:
|
| Часовой пояс GMT +3, время: 10:15. |