PDA

View Full Version : Ext.form.Panel - add/edit record with remote store



john316
19 May 2014, 7:31 AM
I'm fairly new to Ext JS and have been working mostly with data grids thus far. I've now got a simple form panel that needs to read data from a database table, using the "personid" as the unique identifier. The form works as long as there's already a record in the db to read and edit. My question is, how do I automatically insert a new record if one doesn't exist for this personid when the user loads this page? My page and model code is below. Any help would be greatly appreciated!

Form Panel Code:


Ext.define('DataMine.view.fyc.KarateList', {
extend: 'Ext.form.Panel',
alias: 'widget.karatelist',
frame: true,
bodyBorder: false,
border: false,


defaults: {xtype:'textfield'},
items: [
{xtype:'textfield', fieldLabel:'Weight', name:'weight'},
{xtype:'textfield', fieldLabel:'Height', name:'heightfeet'},
{
fieldLabel:'Belt Size', xtype:'combobox', name:'beltsize',
store: [['0','0'],['00','00'],['000','000'],['1','1'],['2','2'],['3','3'],['4','4'],['5','5'],['6','6'],['7','7'],['8','8'],['9','9'],['10','10']]
},
{
fieldLabel:'Gi Size', xtype:'combobox', name:'gisize',
store: [['0','0'],['00','00'],['000','000'],['1','1'],['2','2'],['3','3'],['4','4'],['5','5'],['6','6'],['7','7'],['8','8'],['9','9'],['10','10']]
},
{
fieldLabel:'Current Rank', xtype:'combobox', forceSelection: true, name:'currentrank',
store: [['White','White'],['Yellow','Yellow'],['Orange','Orange'],['Green','Green'],['Blue','Blue'],['Purple','Purple'],
['3rd Brown','3rd Brown'],['2nd Brown','2nd Brown'],['1st Brown','1st Brown'],['1st Black','1st Black'],
['2nd Black','2nd Black'],['3rd Black','3rd Black'],['4th Black','4th Black'],['5th Black','5th Black'],
['6th Black','6th Black'],['7th Black','7th Black'],['8th Black','8th Black'],['9th Black','9th Black'],['10th Black','10th Black']
]
},
{fieldLabel:'Date Earned', name:'dateearned', xtype:'datefield', format:DataMine.datetimeFormat, submitFormat:'m/d/Y h:i:a'},
{
fieldLabel:'Next Rank', xtype:'combobox', forceSelection: true, name:'nextrank',
store: [['White','White'],['Yellow','Yellow'],['Orange','Orange'],['Green','Green'],['Blue','Blue'],['Purple','Purple'],
['3rd Brown','3rd Brown'],['2nd Brown','2nd Brown'],['1st Brown','1st Brown'],['1st Black','1st Black'],
['2nd Black','2nd Black'],['3rd Black','3rd Black'],['4th Black','4th Black'],['5th Black','5th Black'],
['6th Black','6th Black'],['7th Black','7th Black'],['8th Black','8th Black'],['9th Black','9th Black'],['10th Black','10th Black']
]
},
{fieldLabel:'Next Test Date', name:'testdate', xtype:'datefield', format:DataMine.datetimeFormat, submitFormat:'m/d/Y h:i:a'},
{
fieldLabel:'Earned', xtype:'combobox', forceSelection: true, name:'earned',
store: [['No','No'],['Yes','Yes']
]
},
{
fieldLabel:'Semester Fee', xtype:'combobox', forceSelection: true, name:'semesterfee',
store: [['Due','Due'],['Paid','Paid'],['Waived','Waived']
]
},
{
fieldLabel:'Test Fee', xtype:'combobox', forceSelection: true, name:'testfee',
store: [['Due','Due'],['Paid','Paid'],['Waived','Waived']
]
}
],


buttonAlign:'center',
buttons: [
{text:'Edit', itemId:'edit', width:70, handler:function(btn){
var form = this.up('form');
var fields = form.query('textfield');
Ext.Array.each(fields,function(field) {
field.setReadOnly(false);
});
this.hide();
form.down('#save').show();
}},
{text:'Save', itemId:'save', width:70, hidden:true, handler:function(btn){
var form = this.up('form');
form.updateRecord();
var rec = form.getRecord();
rec.save();
var fields = form.query('textfield');
Ext.Array.each(fields,function(field) {
field.setReadOnly(true);
});
btn.hide();
form.down('#edit').show();
}},
{text:'Close', width:70, handler:function(btn){
var panel = this.up('form').up('panel').up('panel');
panel.close();
}}
],


initComponent: function() {
this.callParent(arguments);
console.log('DataMine.view.fyc.KarateList.initComponent()\t this.record=%o', this.record);


var karaterec = Ext.getStore('Karate').findRecord('personid', this.record.get('id'));
if(karaterec) this.loadRecord(karaterec);


this.on('render', function() {
console.log('DataMine.view.fyc.KarateList::render\t this=%o', this);
var fields = this.query('textfield');
Ext.Array.each(fields,function(field) {
field.setReadOnly(true);
});
});
}
});




Model Definition:


Ext.define('DataMine.model.Karate', {
extend: 'Ext.data.Model',
fields: [
{name:'id', mapping:'KarateID', type:'int'},
{name:'personid', mapping:'PersonID', type:'int'},
{name:'weight', mapping:'Weight', type:'int'},
{name:'heightfeet', mapping:'HeightFeet', type:'string'},
{name:'beltsize', mapping:'BeltSize', type:'int'},
{name:'gisize', mapping:'GiSize', type:'int'},
{name:'currentrank', mapping:'CurrentRank', type:'string'},
{name:'dateearned', mapping:'DateEarned', type:'date', dateFormat:'Y-m-d H:i:s'},
{name:'nextrank', mapping:'NextRank', type:'string'},
{name:'testdate', mapping:'TestDate', type:'date', dateFormat:'Y-m-d H:i:s'},
{name:'earned', mapping:'Earned', type:'string'},
{name:'semesterfee', mapping:'SemesterFee', type:'string'},
{name:'testfee', mapping:'TestFee', type:'string'}

],
idProperty:'id',
proxy: {
type: 'direct',
reader: {
root: 'data',
totalProperty: 'total'
},
api: {
create: DataMine.Direct.Karate.create,
read: DataMine.Direct.Karate.read,
update: DataMine.Direct.Karate.update,
destroy: DataMine.Direct.Karate.delete
}
}
});

jsakalos
19 May 2014, 7:51 AM
You can create a new record with Ext.create() and then pass the instance to form.loadRecord() call.

scottmartin
19 May 2014, 7:58 AM
See if setting idParam in your direct proxy helps. I see you have 'id' set and that should be the default.

The new record id should be updated as shown in this video:
http://screencast.com/t/gFbJ5ysE2Ey

john316
19 May 2014, 9:21 AM
Scott, I think that's where the issue is but I'm unsure on what the solution is. This form exists on one of many tabs that are loaded when the user selects a client record from the clients database. When this tab is selected, the parent container tab calls:


var karateTab = Ext.create('Ext.panel.Panel', {
title: 'Karate',
layout:'fit',
border:false, bodyBorder: false,
items: [Ext.widget('karatelist', {record:this.record, hideHeader:true, border:false, bodyBorder:false})]
});


From here, the client record is passed, with the "personid" from the "persons" table. The form is inserting/updating a record in the "karate" table. In the Ext.Direct file, "karate.php", I have the PK from the persons table being passed but there is no record in the karate table yet, so I need to do a phantom insert...I have figured out how to do this on a data grid, but the form panel context has me lost. Here's the Ext.Direct file:



<?php
class Karate extends Store
{
protected $_db;
protected $_result;
public $results;


public function __construct()
{
parent::__construct();


$this->table = "Karate";
$this->fields = array(
array('id', 'KarateID', 'i'),
array('personid', 'PersonID', 'i'),
array('weight', 'Weight', 'i'),
array('heightfeet', 'HeightFeet', 's'),
array('beltsize', 'BeltSize', 'i'),
array('gisize', 'GiSize', 'i'),
array('currentrank', 'CurrentRank', 's'),
array('dateearned', 'DateEarned', 's'),
array('nextrank', 'NextRank', 's'),
array('testdate', 'TestDate', 's'),
array('earned', 'Earned', 's'),
array('semesterfee', 'SemesterFee', 's'),
array('testfee', 'TestFee', 's')
);
$this->key = $this->fields[0][1];
return $this->db;
}
}
?>


Can I do an 'if(rec.phantom)' type of insert here?

scottmartin
19 May 2014, 10:01 AM
>>> but there is no record in the karate table yet,

I am a bit confused on your approach ...

The procedure is to insert a record into the store, then send that info to the server/DB to insert this record and then this new record is returned back to the client with the new auto-created id that is used to update the inserted record in the store.

Is this the process your using?

john316
19 May 2014, 10:12 AM
Yes, that's exactly how everything in my app is set up and functioning. My issue is I've never done this with a form panel before. The client record exists, and I need this form available to anyone who exists in the db, so I added a simple tab with a form panel. I just can't get my head around the syntax of something like:



var karaterec = Ext.getStore('Karate').findRecord('personid', this.record.get('id'));
if(karaterec) this.loadRecord(karaterec);

if (!karaterec) {
var store = Ext.create('Ext.data.Store',{
model: Ext.getStore('Karate').model
});
var karaterec = Ext.create('DataMine.model.Karate',{
personid: personid,
});
store.insert(0,rec);
store.reload();
}


The first two lines work and load the record if I manually insert it in to the db...it's the creating of the model and inserting in to the store that is eluding me here...

scottmartin
19 May 2014, 10:34 AM
If you are receiving the data, the as Saki mentioned, you can use form.loadRecord(returnedRecord) in the callback.

Reload is just reloading the entire store again.

john316
19 May 2014, 11:09 AM
Indeed. That's the issue. I am receiving the data if the data exists (if there's a record in the karate table matching the currently loaded record). However, if there's no record in the karate table, there's no "karaterec" to load in the loadRecord call. Thus, I need to insert a new record in to the karate table and carry the "personid" from the currently loaded record in to that insert. That's what I'm trying to do here...Sorry if that wasn't clear. As I mentioned, I'm fairly new to Ext JS...

scottmartin
19 May 2014, 11:19 AM
From your description, it sounds like you are trying to insert the record into the store after you receive the record from the server.

Where in my scenario, I am inserting a record into the store and that record gets updated after the server creates the record and returns that record back.

Did I read that correctly?

john316
19 May 2014, 11:29 AM
Ah, I see the difference. Yes, in my case, in the current code, it only has the ability to load the current record, if it exists, and then update that record. So that's the piece I'm missing and don't see in any of my books...it all makes sense when I'm using a data grid and have an "Add" button, with which I can specify the required fields to add a new record to the store and then update the db, etc. Doing this in a form panel is where I'm lost.

scottmartin
19 May 2014, 11:49 AM
The alternative is to load the new records from the server and then use form.loadRecord(currentRec) from grid selection.

john316
20 May 2014, 2:57 PM
I figured this out:



if(!karaterec) {
var karaterec = Ext.create('DataMine.model.Karate', {
personid: this.record.get('id')
});
Ext.getStore('Karate').add(karaterec);
}
this.loadRecord(karaterec);

john316
20 May 2014, 2:58 PM
Thanks for all your help guys. I REALLY appreciate it! And my apologies for newbie ignorance. Thanks for your patience.