Extjs state manager - save state from a dynamic form - extjs

I have a form that I add on click new fields. http://jsfiddle.net/Zb8DV/
the user can add his input and click on save.
I want onsave event to store the state in the cookie.
Next time when he enter to the form, I want to load the state, generate the fields in put the values last time he entered to the form.
So if you look at the form bellow:
you click on "add field" and a new field will be generated, after you add fields and put values, I want to save the state and load it next time...
Ext.state.Manager.setProvider(new Ext.state.CookieProvider());
Ext.create('Ext.form.Panel', {
renderTo: Ext.getBody(),
width: 500,
bodyPadding: 10,
title: 'Stateful',
stateful : true,
stateId : "MyFormState",
items: [{
xtype: 'button',
text: 'add field',
count: 0,
handler: function () {
this.count += 1;
var me = this;
this.up("form").add([{
"xtype": 'textfield',
name: 'field' + me.count,
fieldLabel: 'field ' + me.count
}]);
}
}, {
xtype: 'button',
margin : '10 10 10 100',
text: 'Save form state on click here',
handler : function(){alert("how do I load the panel with the state saved in cookie??")}
}],
});

In your button handler you can get values from form with getValues() method and then store values into cookies with Ext.state.Manager.set() method.
handler : function(btn){
var form = btn.up('form');
var values = form.getValues();
Ext.state.Manager.set('formFieldValues', values);
}
Restore form state from cookies you can in listener for form afterrender event. For getting form state from cookie you can use Ext.state.Manager.get() method.
listeners: {
afterrender: function(form) {
var values = Ext.state.Manager.get('formFieldValues');
if (values) {
console.log(values);
Ext.Object.each(values, function(key, value) {
form.count += 1;
form.add({
xtype: 'textfield',
name: 'field' + form.count,
fieldLabel: 'field ' + form.count,
value: value
});
});
}
}
}
Fiddle with complete example: https://fiddle.sencha.com/#fiddle/32e

Related

Input field doesn't get cleared after choosing the value in the ExtJS tag field

I have the ExtJS tag field with anyMatch = true. Now if you type AB it will show the result and once you choose the selection it will clear the input you have entered i.e. AB Now when you have anyMatch= true that time if I type HI it will show you the result but when you choose the value the input field doesn't get cleared. I saw the ExtJS Tag field code it is handled explicitly in clearInput method. I wanted to know why this is implemented in this way ?
Below is the sample code
Ext.create('Ext.form.Panel', {
title: 'Tag Field Example',
width: 1000,
bodyPadding: 10,
items: [{
xtype: 'fieldcontainer',
labelWidth: 100,
layout: 'hbox',
items: [{
xtype: 'fieldcontainer',
defaults: {
flex: 1,
},
layout: 'hbox',
items: [{
xtype: 'tagfield',
minChars: 1,
anyMatch: true,
allowBlank: true,
margin: '5 5 5 5',
fieldLabel: 'Tag Field 1',
name: 'tagField1',
store: ['ABC D', 'EFG HI', 'C'],
queryMode: 'local',
filterPickList: true,
emptyText: 'Multi Select...'
}]
}]
}],
renderTo: Ext.getBody()
});
This seems to be a bug. If you take a look at the clearInput method from the tagfield class definition, and specifically at the section with the early return:
if (!Ext.String.startsWith(lastDisplayValue, inputValue, true)) {
return;
}
You can see that they discard clearing of the field if the last selected tag field value does not start with the typed input value ('abc d' starts with 'ab' so the field is cleared; 'efg hi' does not start with 'hi' - so the clearing is discarded).
This will clearly not work when you have the anyMatch config enabled.
The early return section from above, should be something like this:
if (!me.anyMatch) {
if (!Ext.String.startsWith(lastDisplayValue, inputValue, true)) {
return;
}
} else {
if (lastDisplayValue.toLowerCase().indexOf(inputValue.toLowerCase()) === -1) {
return;
}
}
We keep the initial check when anyMatch is not enabled, otherwise, we check if the typed input values is included in the last selected tag field value.
Here is a fiddle with the proposed override: https://fiddle.sencha.com/#view/editor&fiddle/32q0
I used arrays for multi string values (list item: Lincoln Abraham, input value: Abraham Lin).
That way method to checks if it matches properly.
In my implenmentation last part of the input string is used as wildcarded string. It also solves the problem where list item is reversed compare to input string, which was in my case.
clearInput: function() {
var me = this,
valueRecords = me.getValueRecords(),
inputValue = me.inputEl && me.inputEl.dom.value,
lastDisplayValue;
if (valueRecords.length && inputValue) {
lastDisplayValue = valueRecords[valueRecords.length - 1].get(me.displayField);
let inputValueArr = inputValue.split(' ');
let lastDisplayValueArr = lastDisplayValue.split(' ');
let matchCount = 0;
Ext.each(inputValueArr, function(iv, idx1, arr1) {
Ext.each(lastDisplayValueArr, function(ldv, idx1, arr2) {
if (!me.anyMatch) {
if (Ext.String.startsWith(ldv, iv, true)) {
matchCount++;
}
} else {
if (ldv.toLowerCase().indexOf(iv.toLowerCase()) !== -1) {
matchCount++;
}
}
});
});
if (matchCount < inputValueArr.length) {
return;
}
me.inputEl.dom.value = '';
if (me.queryMode === 'local') {
me.clearLocalFilter();
// we need to refresh the picker after removing
// the local filter to display the updated data
me.getPicker().refresh();
}
}
}

How to solve this error "Uncaught TypeError: Cannot call method 'getForm' of undefined "

I tried to add edit button functionality in grid panel. I want to open an edit window on edit button click for updating grid row record using Ext Window Form which contains fields like (Shift Name, Time, Total, Requirement, Note). The window form is created, but the row values that I have selected in grid are not set in form fields.
I tried to use this code:
Ext.getCmp('shiftWindow').getForm().setValues(selection[0].data);
but it's giving the following error
Uncaught TypeError: Cannot call method 'getForm' of undefined
Here is my code:
var shiftWindow = Ext.create('Ext.window.Window', {
title: 'Edit Shift',
resizable: false,
id: 'shiftwindow',
width: 465, //bodyPadding: 5, modal: true, store: shiftStorePlanner,
items: {
xtype: 'form',
id: 'idFormShift',
bodyPadding: 10,
items: shiftViewModelPlannerData
},
buttons: [{
text: 'Save',
cls: 'planner-save-button',
overCls: 'planner-save-button-over',
handler: function () {
var wi = this.up('.window')
var form = Ext.getCmp('idFormShift');
if (form.isValid()) {
shiftTimemappingarray = [];
getShiftTime();
//this.up('.window').close();
}
}
}, {
text: 'Cancel',
handler: function () {
this.up('.window').close();
}
}]
});
var host1 = Ext.getCmp('plannershifteditor');
var selection = host1._shiftPlannerGrid.getSelectionModel().getSelection();
if (selection.length === 0) {
return;
}
selection[0].data.ShiftName = selection[0].data.ShiftName.replace('(ARCHIVED)', '').trim(); //if edit Archive record then text name show without (ARCHIVED)
//shiftWindow.getForm().setValues(selection[0].data);
Ext.getCmp('shiftWindow').getForm().setValues(selection[0].data);
//Ext.getCmp('shiftWindow').setValue(selection[0].data);
shiftWindow.show();
There's no getForm method in the window. You can get the form using shiftWindow.down('form'). Here's the snippet:
shiftWindow.down('form').form.setValues(selection[0].data)

on change event datepicker in Ext.form.DateField not working

I have html span for datepicker like this
<span id="spanLimitFBClaim"></span>
then i call it's first.js
$("#spanLimitPaymentDate").datepicker("LimitPaymentDate")
datepicker comes form another global.js
$.fn.datepicker = function (id) {
var mydate = new Ext.form.DateField({
xtype: 'datepicker',
format: 'd-M-Y',
margin: '2 0 2 0',
renderTo: Ext.get($(this).attr("id")),
cls: 'sa-datepicker',
inputId: id,
value: new Date()
});
$("#" + id).attr("readonly", true);
}
it is works. the problem is. i want to get change event. i try to add in global.js the listener like this
$.fn.datepicker = function (id) {
var mydate = new Ext.form.DateField({
xtype: 'datepicker',
format: 'd-M-Y',
margin: '2 0 2 0',
renderTo: Ext.get($(this).attr("id")),
cls: 'sa-datepicker',
inputId: id,
value: new Date(),
listeners: {
select: function () {
console.log('Date selected: ', this.getValue());
}
}
});
$("#" + id).attr("readonly", true);
}
and it works. i see the value on global.js (console.log) the problem is how to add it in my span (from the first.js). because i do below code is not working
$("#spanLimitPaymentDate").datepicker("LimitPaymentDate", {
listeners: {
select: function () {
console.log('Date selected: ', this.getValue());
}
}
});
i'm very newbie in ext.js, seems i was typo in using it :(
Many thanks
In the first version, you set the listener in the config of the field you create in the function.
In the second version, you set the listener as the second argument to said function, but that function only takes one argument. So the config you set there is omitted.
It should work if you change your function like this:
$.fn.datepicker = function (id,config) {
var me=this;
var mydate = new Ext.form.DateField(
Ext.apply(config,{
xtype: 'datepicker',
format: 'd-M-Y',
margin: '2 0 2 0',
renderTo: Ext.get($(me).attr("id")),
cls: 'sa-datepicker',
inputId: id,
value: new Date()
});
);
$("#" + id).attr("readonly", true);
}
and then call
$("#spanLimitPaymentDate").datepicker("LimitPaymentDate", {
listeners: {
select: function (picker) {
console.log('Date selected: ', picker.getValue());
}
}
});

Updating a value on an Ext.form.Panel

The following should be trivial, but I cannot get it to work:
I have the following Ext.form.Panel:
Ext.define('EvaluateIt.view.SiteEvaluationForm', {
extend: 'Ext.form.Panel',
alias : 'widget.siteEvaluationForm',
id: 'evaluationId',
requires: [
'Ext.form.Panel',
'Ext.form.FieldSet',
'Ext.field.Url',
'Ext.field.Select',
'Ext.field.Hidden'
],
config: {
// We give it a left and top property to make it floating by default
left: 0,
top: 0,
// Make it modal so you can click the mask to hide the overlay
modal: true,
hideOnMaskTap: true,
// Set the width and height of the panel
//width: 400,
//height: 330,
width: Ext.os.deviceType == 'Phone' ? screen.width : 300,
height: Ext.os.deviceType == 'Phone' ? screen.height : 500,
scrollable: true,
layout: {
type: 'vbox'
},
defaults: {
margin: '0 0 5 0',
labelWidth: '40%',
labelWrap: true
},
items: [
{
xtype: 'textfield',
name: 'address',
label: 'Address',
itemId: 'address'
},
{
xtype: 'hiddenfield',
itemId: 'imageUriId',
name: 'imageUri'
},
{
xtype: 'button',
itemId: 'siteImage',
text: 'Take Photo'
},
{
xtype: 'button',
itemId: 'save',
text: 'Save'
}
]
}
});
Which gets opened from an onItemDisclosure in a list view, and thus has a record bound to it.
When the 'siteImage' button is tapped, the user selects an image from the photo gallery and the uri is written to a temporary store for processing. This part works just fine.
What I need to do: When 'save' in the above form is tapped I need to take the uri from the temporary store and write it to the same store that all of the values from the above form get saved to.
To do this, I have the following method:
onSaveSiteEvaluation: function(button) {
console.log('Button Click for Save');
//var form = button.up('panel');
var form = Ext.getCmp('evaluationId');
//get the record
var record = form.getRecord();
//get the form values
//var values = form.getValues();
// return a clone for updating of values
var values = Ext.clone(form.getValues());
//if a new siteEvaluation
if(!record){
var newRecord = new EvaluateIt.model.SiteEvaluation(values);
Ext.getStore('SiteEvaluations').add(newRecord);
}
//existing siteEvaluation
else {
// get image uri from temp store
var images = Ext.create('EvaluateIt.store.ImageQueue');
images.queryBy(function(record,id){
images = Ext.getStore(images);
if (images.getCount() > 0) {
var uri = record.get('src');
// image = Ext.getCmp('imageUri');
//image = form.setValue(uri);
//form.getCmp('imageId').setValue(uri);
console.log('URI: ' + uri);
// THIS DOES NOT WORK!!
form.setValues({
imageUri: uri
})
//record.set('imageUri',uri)
console.log('imageUri: '+ record.get('imageUri'));
}
});
// do stuff
record.set(values);
}
form.hide();
//save the data to the Web local Storage
Ext.getStore('SiteEvaluations').sync();
},
Everything in this method works EXCEPT where I write the value of the uri to the form
form.setValues({
imageUri: uri
})
I've tried making 'uriImage' as an xType of hiddenfield and textfield, I've tried cloning the values from the form, etc. all with absolutely no luck in updating the actual attribute imageUri in the store (NOTE: All other form values are updated just fine). What am I missing? Thanks!
UPDATE
This works:
images.queryBy(function(iRecord,id){
images = Ext.getStore(images);
if (images.getCount() > 0) {
var uri = iRecord.get('src');
// update store with URI
form.setValues({
imageUri: uri
})
values = form.getValues();
record = form.getRecord();
}
});
// do stuff
record.set(values);
All's well that ends well!
Because Ext.form.Panel doesn't have setValue method. You first need to get basic form out of it:
form.getForm().setValue();
UPDATE: My bad, I was looking at the ExtJs docs and not Sencha Touch. your form does have setValue method.
After you call setValues(), can you go getRecord() again? Also looks like your record internal variable is defined twice. That should not be an issue, but...

How to get form field value in onclick event

I am using this article of architecture http://blog.extjs.eu/know-how/writing-a-big-application-in-ext/
in my code:
I have this Application.DashBoardForm.js in this i want to pass the value of the fromdate in the onclick event function , how can i pass the fromdate value ?
Ext.apply(Ext.form.VTypes, {
daterange : function(val, field) {
var date = field.parseDate(val);
if(!date){
return false;
}
if (field.startDateField) {
var start = Ext.getCmp(field.startDateField);
if (!start.maxValue || (date.getTime() != start.maxValue.getTime())) {
start.setMaxValue(date);
start.validate();
}
}
else if (field.endDateField) {
var end = Ext.getCmp(field.endDateField);
if (!end.minValue || (date.getTime() != end.minValue.getTime())) {
end.setMinValue(date);
end.validate();
}
}
/*
* Always return true since we're only using this vtype to set the
* min/max allowed values (these are tested for after the vtype test)
*/
return true;
}
});
Application.DashBoardForm= Ext.extend(Ext.FormPanel, {
border:false
,initComponent:function() {
var config = {
labelWidth: 125,
frame: true,
title: 'Date Range',
bodyStyle:'padding:5px 5px 0',
width: 350,
defaults: {width: 175},
defaultType: 'datefield',
items: [{
fieldLabel: 'Start Date',
name: 'fromdate',
id: 'fromdate',
vtype: 'daterange',
value : new Date(),
endDateField: 'todate' // id of the end date field
},{
fieldLabel: 'End Date',
name: 'todate',
id: 'todate',
vtype: 'daterange',
value : new Date(),
startDateField: 'fromdate' // id of the start date field
}]
,buttons: [{
text: 'Go',
onClick : function () {
// here i want to access the value of the form field
// how can i access the fromdate value so that i pass it to grid
console.log(this.getForm());
var win = new Ext.Window({
items:{xtype:'DashBoardGrid',fromdate:this}
});
win.show();
}
}]
}; // eo config object
// apply config
Ext.apply(this, Ext.apply(this.initialConfig, config));
Application.DashBoardForm.superclass.initComponent.apply(this, arguments);
} // eo function initComponent
,onRender:function() {
// this.store.load();
Application.DashBoardForm.superclass.onRender.apply(this, arguments);
} // eo function onRender
});
Ext.reg('DashBoardForm', Application.DashBoardForm);
How can I pass the value of from date here in onclick function?
Being that you gave the field an ID of 'fromdate', you can reference it using Ext.getCmp() and from there call its getValue() method:
var field = Ext.getCmp('fromdate');
var win = new Ext.Window({
items: {
xtype: 'DashBoardGrid',
fromdate: field.getValue()
}
});
Set the scope of your button 'Go', so that you will have access to form within the handler method. By doing this, you will have access to the form from the handler method.
Now, to get access to the form element, you can use ref property or use find*() methods available in Ext.form.FormPanel to get the form element.
text: 'Go',
scope: this,
handler: function () {
fromdate = this.findById('fromdate');
// extract date value and use it...
value = fromdate.getValue();
}
When using ref property, set a ref for the formdata field:
ref: '../formdate'
fieldLabel: 'Start Date',
name: 'fromdate',
id: 'fromdate',
vtype: 'daterange',
value : new Date(),
endDateField: 'todate' // id of the end date field
And you should be able to access the form element through the form object in the handler.
this.formdate.getValue()

Resources