I need to allow my users to submit multiple property addresses by clicking a button that will insert a fieldset with extra text fields. I can do this simply with form.insert(index, component); However, that index will change after the user adds an additional property. For example, the index to add the extra properties is after the 7th component, making the index 7. But when you insert it at 7, it's index is now 7 and the next property will be inserted above it. This effect is further compounded when you try to do this with contact emails and numbers in the same form. So my question is, how can I get the index of the component in the form that I wish to insert the extra fields after?
fieldset.items.getCount()
Or am I missing something?
not exactly straight forward, but not too bad either. take a look at the following code: the first part is the button handler to add a set of fields, the second is the actual function that creates the indexed fields.
handler:function () {
var parts = this.up('fieldset'),
index = parts.query('fieldcontainer').length, //calculate existing Part line items
fields = this.up('window').createPartFieldContainer(index);
parts.add(fields);
}
createPartFieldContainer:function (index) {
index = index || 0;
return {
xtype:'fieldcontainer',
items:[
{
xtype:'textfield', fieldLabel:'Item',
name:'lineItem[' + index + '].itemNumber', width:100,
emptyText:'Part Number'
}
]
}
}
Related
I have been playing with ReactTable v7 for a while and have encountered the following problem: when the table is sorted and uses paginator sometimes adding (or editing) a row causes it to be outside the current page.
You can see the problem here:
https://codesandbox.io/s/github/tannerlinsley/react-table/tree/master/examples/material-UI-kitchen-sink
Sort the table by First Name
Press add
Enter a record with First Name "zzzzz"
The record is added but is currently hidden which confuses users.
Is there a "standard" way to fix the issue? Am I missing something?
In v6 I have done a workaround for it:
React.useEffect(() => {
if (editedElementId && reactTable) {
const { data } = reactTable.props;
if (data && data.length > 0) {
const internal = reactTable.getResolvedState();
let position = -1;
internal.sortedData.forEach((row, i) => {
if (row._original.id === editedElementId) position = i;
});
if (position >= 0) {
const pageNumber = Math.floor(position / pageSize);
setPage(pageNumber);
} else {
alert.info("Element not visible");
}
}
}
}, [editedElementId]);
...
<ReactTable
ref={(r) => {setReactTable(r);}}
...
But maybe there is a bulit-in way to achieve it?
There is not currently a way to only sort the elements which are currently being displayed, no.
React Table v7's useSortBy hook sorts the entirety of the input data array, so sorting by First Name descending (A->Z) naturally places 'ZZZZZZ' at the end of the list, which will be hidden due to pagination. The v7 way of doing it would probably be similar to what you are doing already, using the exposed properties from the useTable hook instead of reactTable.resolvedState() and etc. Another way to do it would be to write your own custom sortBy method and only sort the items [0...n] where n is the number of currently displayed items.
As a side note, since the autoResetSortBy property is true by default in the example you linked, the step of sorting on First Name is irrelevant -- since the function which adds a new user to the list mutates the data array, the sorting method is reset. That function appends the new user to the end of the list, so it will always be on a new page, even if the "Rows per page" option is set to "All". Both issues can be fixed by setting autoResetSortBy to false, and changing the pageSize in addUserHandler.
I know it's been asked million+1 times. But i've found no help in those questions/answers.
I have 2 arrays of 2 different objects one string property is used to uniquely identify them. This would be the key to sort about, but said object prop names are not equal (accessValue, modifiedOption). But their values are!
Object1: { ... accessValue, ... };
Object2: { ..., modifiedOption, ... };
array1:Object1[];
array2:Object2[];
I'd like to sort array1 based on the object indencies of array2.
So all of array1 items'd be in the same order as array2.
These two arrays are used to model a connected dropdown selection system, which can be added to are removed from. The Addition is screwing me over (lastly added item is appended to the first place and not the last) probably because of filter below?
What I use to add new dropdowns:
addFieldRow() {
this.fieldRows.push(0); // since desired selection is not known yet but need to populate the array that represents the 1st selection so a 2nd main selection dropdown will appear on screen
...
}
public onSelect() {
// if a selection is happened check the values of editOptions (contains data about all main selectable options)
this.fieldRows = this.editOptions.filter(
option => this.selectedOptions.some(el => el.modifiedOption === option.accessValue)
);
this.disableSelected(); // disable already selected items (not related to my issue)
this.optionSelected = true; // this is just for button disabled toggle
}
So either i need to figure out my addRow logic (if it has any flaws) or implement a sorting utility to make sure that the objects of fieldRows are in the same order as selectedOptions' -> since this models the selection directly.
I cannot really add a stackblitz since it's hard to model my current state.
Okay I am a complete idiot!
Since I know the current index (since i am looping through fieldRows).
All I had to do is replace this:
public onSelect() {
this.fieldRows = this.editOptions.filter(
option => this.selectedOptions.some(el => el.modifiedOption === option.accessValue)
);
With this:
public onSelect(index) {
this.fieldRows[index] = this.editOptions.find(option => this.selectedOptions[index].modifiedOption === option.accessValue);
this.disableSelected();
this.optionSelected = true;
}
Now it works correctly.
I have a multiselect grid where I can get schools.getSelectionModel().getSelection();
there is an object called data, I want to get a field within the data; lets say school_name
How I'll do it?
I've tried
schools.getSelectionModel().getSelection().data
schools.getSelectionModel().getSelection(data)
schools.datagetSelectionModel().getSelection()
they did not work.
You have to use Ext.each to iterate over the array of records..
Ext.each(schools.getSelectionModel().getSelection(), function(record, index, allRecords) {
console.log(record.get('school_name');
});
This:
schools.getSelectionModel().getSelection()[0].get('school_name')
should give you a 'school_name' field from first row selected (which is also a first record in selection).
To iterate over all selected rows do:
var selectedSchools = schools.getSelectionModel().getSelection();
for (i in selectedSchools) {
console.log(schools[i].get('school_name')); //this will log school name to firebug console - you can do whatever you need
}
When adding a rows to a grid, and then clicking on it, it gets selected (and highlighted). Then, clicking elsewhere but the new row remains highlighted (so now there are to highlighted rows).
Please, does anyone know what the problem could be? How to make it behave normally, i.e. clicking a row deselects (de-highlights) the other one?
After I reload the page (so the new row is not new anymore), everything works as expected.
Edit: Here's the code for adding rows:
var rec = new store.recordType({
test: 'test'
});
store.add(rec);
Edit 2: The problem seems to be listful: true. If false, it works! But I need it to be true so I'm looking at this further... It looks like as if the IDs went somehow wrong... If the ID would change (I first create the record and then the server returns proper ID, that would also confuse the row selector, no?)
(Note, correct as ExtJS 3.3.1)
First of all, this is my quick and dirty hack. Coincidentally I have my CheckboxSelectionModel extended in my system:-
Kore.ux.grid.CheckboxSelectionModel = Ext.extend(Ext.grid.CheckboxSelectionModel, {
clearSelections : function(fast){
if(this.isLocked()){
return;
}
if(fast !== true){
var ds = this.grid.store,
s = this.selections;
s.each(function(r){
//Hack, ds.indexOfId(r.id) is not correct.
//Inherited problem from Store.reader.realize function
this.deselectRow(ds.indexOf(r));
//this.deselectRow(ds.indexOfId(r.id));
}, this);
s.clear();
}else{
this.selections.clear();
}
this.last = false;
}
});
And this is the place where the clearSelections fails. They try to deselect rows by using ds.indexOfId(r.id) and it will returns -1 because we do not have the index defined remapped.
And this is why we can't find the id:-
http://imageshack.us/photo/my-images/864/ssstore.gif/
Note that the first item in the image is not properly "remapped". This is because we have a problem in the "reMap" function in our Ext.data.Store, read as follow:-
// remap record ids in MixedCollection after records have been realized. #see Store#onCreateRecords, #see DataReader#realize
reMap : function(record) {
if (Ext.isArray(record)) {
for (var i = 0, len = record.length; i < len; i++) {
this.reMap(record[i]);
}
} else {
delete this.data.map[record._phid];
this.data.map[record.id] = record;
var index = this.data.keys.indexOf(record._phid);
this.data.keys.splice(index, 1, record.id);
delete record._phid;
}
}
Apparently, this method fails to get fired (or buggy). Traced further up, this method is called by Ext.data.Store.onCreateRecords
....
this.reader.realize(rs, data);
this.reMap(rs);
....
It does look fine on the first look, but when I trace rs and data, these data magically set to undefined after this.reader.realize function, and hence reMap could not map the phantom record back to the normal record.
I don't know what is wrong with this function, and I don't know how should I overwrite this function in my JsonReader. If any of you happen to be free, do help us trace up further for the culprit that causes this problem
Cheers
Lionel
Looks like to have multi select enabled for you grid. You can configure the selection model of the grid by using the Ext.grid.RowSelectionModel.
Set your selection model to single select by configuring the sm (selection model) in grid panel as show below:
sm: new Ext.grid.RowSelectionModel({singleSelect:true})
Update:
Try reloading the grid using the load method or loadData method of the grid's store. Are you updating the grid on the client side? then maybe you can use loadData method. If you are using to get data from remote.. you can use load method. I use load method to update my grid with new records (after some user actions like add,refresh etc). Or you could simply reload as follows:
grid.getStore().reload();
Got an issue, and need your advices
I just started writing an editor grid. (I will actually use this grid as a search filter editor, i.e. columns with criteria name, operators and values).
Now, for the value field, I want to have different edit controls for different rows. For instance, when a criteria type is string I want to display a text box, when it's date time, I want a datetime editor.
So the fact is, I need to control the "edit control creation/display" just before editing starts. and it should be different among rows. Unlike the examples I found which are fixed for the columns.
In order to implement this, can you guys please suggest the steps I need to do? I can probably figure out it if one of you can direct me a way.
Thanks and best regards
Actually you can easily accomplish this by dynamically returning different editors and renders depending on the column you're in. In your ColumnModel object you can define something like this below. Note that i'm getting a type property of each record to determine its type. I have an object containing all my different types of editors, and the same for renderers, and then based on the the type i dish out a different editor or renderer for that cell.
editors: { 'default': {xtype:'textfield'},
texttype: {xtype:'textfield'},
numbertype: {xtype:'numberfield'},
combotype: {xtype:'combo'}....... etc. }
getCellEditor: function(colIndex, rowIndex) {
var store = Ext.getCmp('mygrid').getStore();
var field = this.getDataIndex(colIndex);
var rec = store.getAt(rowIndex);
var type = rec.get('type');
if (type in this.editors) {
return this.editors[type];
} else {
return this.editors['default'];
}
},
In the configuration section of your editorgrid, you will need to define your custom editors:
{
xtype: 'editorgrid',
id : 'mygridID',
stripeRows: true,
...
...
,customEditors : {
//configs go here or pre-define the configs prior to this
'columnName1' : new Ext.grid.GridEditor(new Ext.form.Combobox(configObject)),
//configs go here or pre-define the configs prior to this
'columnName7' : new Ext.grid.GridEditor(new Ext.form.CheckBox(configObject))
}
}
use this grid config - in order to select whole rows:
selType: 'rowmodel'