How can I make each value go before each other with react-select - react-select

When you use react-select multi-select option, the default behavior is for each value once selected be inserted after each other.
you can see this behavior on the example site here for the MultiSelect option. https://jedwatson.github.io/react-select/
How can I insert each value component before, instead of after ?
Is there some sort of trick to do this ?
here is a code box.
https://codesandbox.io/s/y8RD0GVWg
Thanks in advance.

The secret to ordering the selected values lays in the function that handles the changes.
It concats each new selection, you can split it into an array and reverse it.
handleSelectChange = value => {
const data = value.split(',');
const d = [
data[data.length-1],
...data.slice(0, data.length - 1),
]
console.log("You've selected:", value, data, d);
this.setState({ value: d });
};

Related

Cannot set a checkbox unchecked once it has been checked against the data with Vue

I am desparately trying to understand what's wrong there and can't figure it out!
I'll try to explain as best as I can, but the code is lengthy and I can't post it easily.
I have a component called "FrameHeader" that includes an input checkbox. This component is called in another component called "Frame", and the frames made from a v-for in another component ("FrameContainer").
In FrameHeader template, I have this:
<input :key="'frame-touchselectbox-'+frameId" type="checkbox"
v-model="touchSelected"
:class="{hidden: !isTouchSelectOn, selectCheckBox: true}"
/>
touchSelected is a computed property defined as such:
computed: {
touchSelected() {
console.log("checking frame touch selected for frame " + this.frameId + " ==> " + store.getters.isFrameTouchSelected(this.frameId));
return store.getters.isFrameTouchSelected(this.frameId);
},
},
where store.getters.isFrameTouchSelected(this.frameId); retrieves a boolean property called "touchSelected" in an object of the state:
The idea is that in the scenario I have, all "touchSelected" properties are first set to false (A), then only the one from one of the frame is set to true (B).
(A):
toggleTouchSelect(state, payload: {frameId: number; toggle: boolean}) {
const newCandidates: number[] = (payload.toggle) ? getAllSiblings(state.frameObjects, payload.frameId): [];
Object.keys(state.frameObjects).forEach((frameKey) => {
Vue.set(
state.frameObjects[parseInt(frameKey)],
"touchSelected",
false
);
Vue.set(
state.frameObjects[parseInt(frameKey)],
"isTouchSelectOn",
newCandidates.includes(parseInt(frameKey))
);
});
},
(B):
touchSelectFrame(state, payload: {frameId: number; isSelected: boolean}) {
Vue.set(
state.frameObjects[payload.frameId],
"touchSelected",
payload.isSelected
);
},
The data I get in the store is correct, I get false/true values where I want them.
However, the checkboxes are not correct. The first time I set one of the frame's property to "true", the corresponding checkbox gets checked. But when I get another frame's property to "true", the previous frame's checkbox doesn't get unchecked. Actually, I see it first being unchecked, then being checked again.
As I said, the data in the state is correct: even when that checkbox revert to checked, the underlying property in the data for that frame is "false".
BUT the weirdest thing is that if only change the checkbox input to a text input (changing the type of the input in the template), the text value is always correct even after the second time I set a frame's property to "true".
So...i'm totally puzzled and can't understand what's happening with those checkboxes.
Sorry for the vague explanation I hope it can still be understandable and that someone will shed a light on that :) Thanks a lot.
Computed props are by default getter-only (reference). That means your checkbox can read the value of touchSelected but can't change its value. You have to use a computed prop with a getter AND a setter. Assuming you have a mutation to change your frameId logic in Vuex:
computed: {
touchSelected: {
get(): {
return store.getters.isFrameTouchSelected(this.frameId);
}
set(newValue): {
store.commit('FRAME_MUTATION', newValue);
}
}
},

how to make row disabled with ag-grid?

I work with ag-grid and i found how to make a column disabled in the doc (https://www.ag-grid.com/documentation-main/documentation.php)
but after reading doc i never find how can i make juste one row disabled.
i have already try editable: params => params.data.active === true.
Maybe i didn't read right or that doesn't exist. Is someone here with some soluce track ?
TL;DR
There is no option in the library to make a single row disabled(both visually and keyboard event based), the only way we could make a single row disabled is by using a customCellRenderer for both header and subsequent cell checkboxes, this allows full control over the checkbox.
Besides this, there are three other ways where you can disable ag-grid checkbox based on value,
1)This is using checkBoxSelection param, it would empty the cell based on the condition.
checkboxSelection = function(params) {
if (params.data.yourProperty) {
return true;
}
return false;
}
This would only disabled click events and style it accordingly,
cellStyle: params => return params.data.status? {'pointer-events': 'none', opacity: '0.4' } : '';
3)This would disable it completely, as you have control over the input, but you may have to use string literals,
cellRenderer: (params) => {
if (params.value) {
return `<input type="checkbox" checked/>`;
}
else {
return `<input type="checkbox" />`;
}
}
You could use customCellRenderer(customCellRendererParams for props), headerCellRenderer(headerCellRendererParams for props) which accepts a complete JSX component.
I think this would be the most helpful, it allows you to choose the cellRenderer component based on the row value for that column. Its very well described in the ag-grid documentation.
I think ag-grid has single row checkbox disablement available natively: https://www.ag-grid.com/angular-data-grid/row-selection/#example-forcing-checkboxes-as-selected

React-Native + Redux: Random number of form fields

I am a newbie to react-native, redux and saga and have run into a use case that I have not been able to find a solution for. I understand how to map state to properties and pass around the state between action, reducer and saga. This makes sense to me so far. This is where things seem to get dicey. I have a form that requires a variable number of form fields at any given time depending upon what is returned from the database.
As an example, let's say I have a structure like this:
{
name: ‘’,
vehicleMake: ‘’,
vehicleModel: ‘’,
carLotCity: ‘’,
carLotState: ‘’,
carLotZipCode: ‘’,
localPartsManufacturers: [{name: ‘’, address: ‘’, zipCode}]
}
Everything from name to carLotZipCode would only require one text field, however, the localPartsManufacturers array could represent any number of object that each would need their own set of text fields per each object. How would I account for this with redux as far as mapping the fields to the state and mapping the state to the properties? I am confused about how to begin with this scenario. I understand how to project mapping when the fields are fixed.
I would keep the data as it is coming from the backend. That way you'll avoid normalizing it. I think we just have to be smarter when rendering the fields. Here's what I'm suggesting:
function onTextFieldChange(name, index) {
// either name = `name`, `vehicleMake`, ...
// or
// name = `localPartsManufacturers` and `index` = 0
}
function createTextField(name, index) {
return <input
type='text'
name={ name }
onChange={ () => onTextFieldChange(name, index) } />;
}
function Form({ fields }) {
return (
<div>
{
Object.keys(fields).reduce((allFields, fieldName) => {
const field = fields[fieldName];
if (Array.isArray(field)) {
allFields = allFields.concat(field.map(createTextField));
} else {
allFields.push(createTextField(fieldName));
}
return allFields;
}, [])
}
</div>
);
}
Form receives all the data as you have it in the store. Then we check if the field is an array. If it is an array we loop over the fields inside and generate inputs same as the other properties createTextField. The tricky part here is how to update the data in the store. Notice that we are passing an index when the text field data is changed. In the reducer we have to write something like:
case FIELD_UPDATED:
const { name, index, value } = event.payload;
if (typeof index !== 'undefined') {
state[name][index] = value;
} else {
state[name] = value;
}
return state;
There is nothing preventing you from keeping a list, map, set or any other object in Redux.
The only thing remaining then, is how you map the state to your props, and how you use them. Instead of mapping a single element from the collection to a prop, you map the entire collection to a single prop, and then iterate over the collection in your render method.
In the action you can pass a new collection back, which is comprised of the form fields making up the parts list. Then, your reducer will replace the collection itself.
Or, upon changing an element in the part collection, you can send an action with its id, find it in the collection in the reducer and replace the element that was changed / add the new one / remove the deleted one.

DataTables - createdRow in conjunction with dynamic column hide/unhide

I implemented a dynamic column visibility to hide/show columns, e.g. DT.columns(5).visible(true) and DT.columns(5).visible(false) to show/hide column 5. I also have a callback for createdRow which let's say makes a html button out of the text in column 5.
Currently in createdRow I check this.api().columns(5).visible() and if true then I proceed to do $('td:eq(5)',row).html('<button>'+data[5]+'</button>') cell content, and if false then I return because otherwise I'd overwrite the current 5th <td> which is not the intended one. But then when I unhide column 5, it comes up as text since I did not run the previous code.
I'd like to be able to run the code and cache the html of the cell in column 5 so that when it's unhidden, it comes up with the intended <button>. What's the best way to do that? The column-visibility event?
Note that I know I can use the render: function (...) {} option for the column, but I do not want to use that because it affects the raw data of the table and affects filtering and searching - I want the raw data to remain unaffected, which is why I was using the createdRow or rawCallback callbacks.
Assume column 5 has visibile: false in the DataTable initialization object which looks like this:
var DT = $('#dt').DataTable({
...
createdRow: function (row, data) {
if (this.api().column(5).visible()) {
$('<button>' + data[5] + </button>')
.appendTo($('td:eq(5)',row).text(''));
}
);
Cheers
Look into using columnDefs and the 'render' function instead...
var DT = $('#dt').DataTable({
...
"columnDefs":[
{
'targets':[0],
'visible':false,
'render':function(data, type, row, meta){
...
}
]
});
https://datatables.net/reference/option/columns.render
https://datatables.net/reference/option/columns.data

Getting id from row clicked on a dgrid List

I just started using dgrid, and going through the dTunes sample, I'm unable to find the id associated with each row in the list. This is pretty remedial on my part, but how would I also get the id I sent from the datasource?
define([
'require',
'dgrid/List',
'dgrid/OnDemandGrid',
'dgrid/Selection',
'dgrid/Keyboard',
'dgrid/extensions/ColumnHider',
'dojo/_base/declare',
'dojo/_base/array',
'dojo/Stateful',
'dojo/when',
'dstore/RequestMemory',
'put-selector/put',
'dojo/domReady!'
], function (require, List, Grid, Selection,
Keyboard, Hider, declare, arrayUtil, Stateful,
when, RequestMemory, put) {
var cstsNode = put(listNode, 'div#cstsCars');
...
var cstsList = new TunesList({}, cstsNode);
var dataCSTS = new RequestMemory({ target: require.toUrl('./dataCSTS.json') });
...
dataCSTS.fetch().then(function (cars) {
cstsCars = arrayUtil.map(cars, pickField('Description'));
cstsCars.unshift('All (' + cstsCars.length + ' CSTS Cars' + (cstsCars.length !== 1 ? 's' : '') + ')');
cstsList.renderArray(cstsCars);
});
...
cstsList.on('dgrid-select', function (event) {
var row = event.rows[0];
console.log(row.id); // shows row number. How do I get the real id or other fields?
console.log(row.data); // shows row text that is displayed ("sample text 1")
console.log(row.data.id); // undefined
});
Here is a snippet of sample data like I'm supplying:
[{"id":"221","Description":"sample text 1"},
{"id":"222","Description":"sample text 2"},
{"id":"223","Description":"sample text 3"}]
I'd like to see the id. Instead, row.id returns 1,2 and 3, ie the row numbers (or id dgrid created?).
You haven't really shown a complete example, but given that you're using a store anyway, you'd have a much easier time if you let dgrid manage querying the store for you. If you use dgrid/OnDemandList (or dgrid/List plus dgrid/extensions/Pagination), you can pass your dataCSTS store to the collection property, it will render it all for you, and it will properly pick up your IDs (since Memory, and RequestMemory by extension, default to using id as their identity property).
The most appropriate place to do what you're currently doing prior to renderArray would probably be in the renderRow method if you're just using List, not Grid. (The default in List just returns a div with a text node containing whatever is passed to it; you'll be passing an object, so you'd want to dig out whatever property you actually want to display, first.)
If you want a header row, consider setting showHeader: true and implementing renderHeader. (This is false in List by default, but Grid sets it to true and implements it.)
You might want to check out the Grids and Stores tutorial.
I think the problem might be that I was modeling my code based on the dTunes sample code, which has 3 lists that behave a little differently than a regular grid.
For now, I'm using the cachingStore that is available in the lists. So the way I get the id:
cstsList.on('dgrid-select', function (event) {
var row = event.rows[0];
var id = storeCSTS.cachingStore.data[row.id - 1].id; // -1 because a header was added
console.log(id);
});
I'm not sure whether this will work if I ever try to do sorting.