I wonder how I can pass to prop conditionally to my react-table accessor.
eg: I have a data like this:
const data = [
{
name: 'Something',
isA: false,
isB: false,
isC: true
},
{
name: 'Something 2',
isA: true,
isB: false,
isC: false
},
{
name: 'Something 3',
isA: false,
isB: false,
isC: true
},
];
and my two columns:
const columns = [
{ Header: 'Name', accessor: 'name' },
{ Header: 'Is What?', accessor:'?' },
];
Here is in second column accessor how will work like that?
accessor will be that which one of isA, or isB, or isC true, so if isA true accessor will be isA, if isB accessor will be isB ....
How to know it?
In your Is What ? accessor, in order to know which data to show, you can have the accessor like this :
{
Header: "Is What?",
accessor: a => (a.isA ? "isA" : a.isB ? "isB" : a.isC ? "isC" : "")
}
Here, if isA is true, you'll see isA in your Cell value. However, if isA is false and isB is true, you'll see isB in your Cell value etc.
Related
So I've done some reading on here and saw that most people recommended against modifying props. Thus, I was wondering if there's a way I can duplicate the prop?
Essentially, I want to duplicate the prop and set it to the state. More specifically, I'm creating a table and one of the props that is passed in is the headers which is an array of objects
headers={[
{id: "Name" , numeric: false, disablePadding: false, label: "Name"},
{ id: 'Weight', numeric: true, disablePadding: false, label: 'Weight' },
{ id: 'Height', numeric: true, disablePadding: false, label: 'Height' }
}]
I want to add a default column s.t. it'll look like
headers={[
{id: "Name" , numeric: false, disablePadding: false, label: "Name"},
{ id: 'Weight', numeric: true, disablePadding: false, label: 'Weight' },
{ id: 'Height', numeric: true, disablePadding: false, label: 'Height' },
{id: "Modify" , numeric: false, disablePadding: false, label: "Modify"}
]}
Thanks for your help! :-)
There are a few techniques you could use without using additional libraries
1. Set the initial state properly
this.state = { headers: this.props.headers.slice(0) }
When modifying the state use the callback technique
this.setState((previousState) => {
// mutate the state a return a new one.
});
How to use slice
Using setState properly
Array object is passed by reference. Instead you can create a new array and then dump the data into the state.
this.state = {
headers: (() => {
return [...this.props.headers, {id: "Modify" , numeric: false, disablePadding: false, label: "Modify"}]
})()
}
Create the component which you have to add.
let newObject = { "id": "Modify" , "numeric": false, "disablePadding": false, "label": "Modify" }
Now, create a duplicate along with the newObject which was created.
const headers = [...this.props.headers, newObject]
Now, set that headers to state variable header.
this.setState({
header: headers
})
I hope this will work for you.
Do this in constructor:
this.state: {fooCopy: this.props.foo};
if you want to store modified prop in state, then make a copy in a local var (try Object.assign or JSON.parse(JSON.stringify(a))), modify it, and then store in state.
I'm sorry to have posted this in here since I tried to go here: help.angular-formly.com but there was no content there or removed.
I have a hide expression as so:
{
key: "rotation_speed",
type: "select",
noFormControl: true,
templateOptions: {
label: 'Animation Speed',
required: true,
placeholder: 'Animation Speed',
valueProp: "value",
labelProp: "name",
options: [
{
'name' : 'Fast Clockwise',
'value' : '-10'
},
{
'name' : 'Medium Clockwise',
'value' : '-5'
}
]
},
hideExpression: 'model.img_type === "regular"',
}
and the formly fields in frontend as this:
<formly-form model="panoFactory.presentation.scenes[$index]" fields="scene_fields"></formly-form>
I verified that the model changes in the frontend but the hideExpression isn't getting updated probably due to some scoping issues. Any help on this would be much appreciated. Thanks!
I have a Backbone.Collection SprachLandList with a model SprachLand.
SprachLand
'use strict'
module.exports = class SprachLand extends Backbone.Model
SprachLandList
"use strict"
SprachLand = require('../models/SprachLand')
module.exports = class SprachLandList extends Backbone.Collection
model: SprachLand
I want to display another collection with Backgrid and this collection has a model with an attribute with an array of ids referencing the SprachLand models.
Now i want to use the SprachlandList collection for the values of a Select2Cell cell in a Backgrid.
Naively i tried
columns = [
{ name: "id", label: "ID", editable: false, cell: "integer" },
{ name: "bez", label: "Bezeichnung", editable: false, cell: "string" },
{ name: "rub.bez", label: "Rubrik", editable: false, cell: "string" },
{ name: "sl", label: "Sprachlandkombinationen", editable: true, cell:
Backgrid.SelectCell.extend({
#sllist is an instance of the SprachLandList
optionValues: sllist
multiple: true
})
}
]
I want the Select widget display the "bez" attribute" and have the "id" attribute as value.
Here is a JSON representation of sllist
"[{"id":1,"bez":"de-DE"},{"id":2,"bez":"fr-FR"},\
{"id":3,"bez":"en-GB"},{"id":4,"bez":"nl-NL"},\
{"id":5,"bez":"it-IT"},{"id":6,"bez":"de-CH"},\
{"id":7,"bez":"fr-CH"},{"id":8,"bez":"it-CH"},\
{"id":9,"bez":"de-AT"}]"
I get an error:
Uncaught TypeError: 'optionValues' must be of type {Array.<Array>|Array.<{name: string, values: Array.<Array>}>}
How can i get an acceptable representation of the SprachLandList collection for optionValues?
After some searching i found Converting Array of Objects into Array of Arrays
After some meddling i have now a possible solution:
columns = [
{ name: "id", label: "ID", editable: false, cell: "integer" },
{ name: "bez", label: "Bezeichnung", editable: false, cell: "string" },
{ name: "sl", label: "Sprachlandkombinationen", editable: true, cell: Backgrid.SelectCell.extend({
optionValues: sllist.map((obj) ->
nobj = obj.attributes
Object.keys(nobj).sort().map (key) ->
nobj[key]
)
formatter:
fromRaw: (rawValue, model) ->
(if _.isArray(rawValue) then rawValue else (if rawValue? then [rawValue] else []))
toRaw: (formattedValue, model) ->
(if not formattedValue? then [] else _.map(formattedValue, (v) ->
parseInt v
))
multiple: true
})
}
]
The formatter is to convert the string values of the select element back to integers after edit.
Is this a correct solution?
I've got a datagrid configured as follows:
<script>
angular.module("KendoDemos", [ "kendo.directives" ]);
function MyCtrl($scope) {
$scope.mainGridOptions = {
dataSource: {
transport: {
read: {
url: "http://localhost:8090/rest/mycodeapi/Salesman?app_name=mycode&fields=FirstName%2C%20LastName&include_count=true",
dataType : 'jsonp',
type: 'GET',
beforeSend: function (req) {
req.setRequestHeader('Authorization', 'b3pilsnuhsppon2qmcmsf7uvj6')
}
},
parameterMap: function(data, type) {
if (type == "read") {
// send take as "$top" and skip as "$skip"
return {
order: data.sort[0]['field'] + ' ' + data.sort[0]['dir'],
limit: data.pageSize,
offset: data.skip
};
}
}
},
schema: {
data : 'record',
total: 'meta.count'
},
pageSize: 5,
serverPaging: true,
serverSorting: true,
sort: { field: "SalesmanID", dir: "asc" }
},
sortable: true,
pageable: true,
mobile: 'phone',
columns: [{
field: "FirstName",
title: "First Name"
},{
field: "LastName",
title: "Last Name"
}]
};
}
</script>
Problem is: on 1st click of the any column, say FirstName, it sorts by ascending order which is fine.
On 2nd click it sorts by descending: still the expected behaviour.
On the 3rd click however, nothing happens and the console reveals "Uncaught TypeError: Cannot read property 'field' of undefined ". This means something happens to the data.sort array after the 2nd consecutive click.
Would appreciate any pointers.
On third click the sorting is removed. You can modify your script like following:
if (type == "read") {
var params = {
limit: data.pageSize,
offset: data.skip
};
if (data.sort && data.sort.length > 0)
params.order = data.sort[0]['field'] + ' ' + data.sort[0]['dir'];
return params;
}
I know this is a bit late, but I was facing the same challenge, and this is what I did to resolve the issue.
Change
sortable: true,
to
sortable: {
allowUnsort: false
},
I have a grid, inside of some column of which I have created a combobox editing UI, using columns.editor function.
My goal is every time a user selects some value from the combobox -while populating a newly created grid record-, this value to be
removed from the list options of a next record's combobox.
One of the things i've tried is shown below:
function equipmentDropDownEditor(container, options) {
var equipmentComboBox = $('<input id="equipmentDropDownEditor" required data-text-field="name" data-value-field="name" data-bind="value:' + options.field + '"/>')
.appendTo(container)
.kendoComboBox({
autoBind: false,
dataSource: equipmentTypesDS,
dataBound: function(e) {
var equipmentData = e.sender.dataSource.data();
if(currentlyInsertedEquipmentTypes.length > 0){
for(var i=0;i<currentlyInsertedEquipmentTypes.length;i++){
$.each( equipmentData, function( index, selectedEquipmentData ) {
if (selectedEquipmentData.name == currentlyInsertedEquipmentTypes[i]){
var dataItem = e.sender.dataSource.at(index);
console.log("dataItem: " + dataItem.name + " is being removed");
e.sender.dataSource.remove(dataItem);
}
});
}
}
}
});
}
I've created a global array variable named "currentlyInsertedEquipmentTypes" inside of which I hold all the user's already selected values
(for example if the user has created 2 records inside the grid and has selected "laptop" option in the combobox of the first and "workstation" option
in the combobox of the second --> currentlyInsertedEquipmentTypes = ["laptop", "workstation"] ).
Inside the combobox dataBound event I check whether the user has already selected values (currentlyInsertedEquipmentTypes.length>0)
and if he has, I locate the corresponding object inside the bound dataSource and I remove it, so that it wont be available in the next record's combobox list.
This is where the whole thing crashes even though the data item removal takes place.
Am i missing something that i should do after the data item removal? Should i rebind the datasource to the combobox in some way?
Any help would be much appreciated.
[EDIT]
---- The combobox datasource code
var equipmentTypesDS= new kendo.data.DataSource({
transport: {
read: {
url: "api/equipment_types",
type: "GET",
data: {
//"equipment_category": 1
},
dataType: "json"
}
},
schema: {
data: "data",
total: "total"
}
});
--- the kendo grid code:
$("#popup_equipment").kendoGrid({
dataSource: {
schema:{
model:{
id: "equipment_type_id",
fields:{
equipment_type_id: { editable: false },
name: { }, //validation: {required: true}, defaultValue: "LAPTOP",
items:{ type: "number", defaultValue:1, validation: { required: true, min: 1} }
}
}
}
},
toolbar: ["create"],
columns: [
{ field: "name", title: "εξοπλισμός", width: "300px", editor: equipmentDropDownEditor, template: "#=name#" },
{ field: "items", title:"πλήθος", width: "80px"},
{ command: ["destroy"], title: " ", width: "100px" }
],
//editable: "inline",//true,
editable:{confirmation: false},
scrollable: false,
selectable: false
});
[EDIT 2]
$("#popup_equipment").kendoGrid({
dataSource: {
schema:{
model:{
id: "equipment_type_id",
fields:{
equipment_type_id: { editable: false },
name: { }, //validation: {required: true}, defaultValue: "LAPTOP",
items:{ type: "number", defaultValue:1, validation: { required: true, min: 1} }
}
}
}
},
toolbar: ["create"],
columns: [
{ field: "name", title: "εξοπλισμός", width: "60%", editor: equipmentDropDownEditor, template: "#=name#" },
{ field: "items", title:"πλήθος", width: "20%"},
{ command: ["destroy"], title: " ", width: "20%" }
],
editable:{confirmation: false},
scrollable: false,
selectable: false,
save: function(e){
console.log("GRID SAVE EVENT! ", e);
var equipment_name = e.values.name;
equipmentTypesDS.get(equipment_name).used = true;
console.log("equipmentTypesDS", equipmentTypesDS);
console.log("END OF GRID SAVE EVENT!");
}
});
function equipmentDropDownEditor(container, options) {
var equipmentComboBox = $('<input id="equipmentDropDownEditor" required data-text-field="name" data-value-field="name" data-bind="value:' + options.field + '"/>')
.appendTo(container)
.kendoComboBox({
autoBind: false,
dataSource: equipmentTypesDS,
});
}
var equipmentTypesDS= new kendo.data.DataSource({
transport: {
read: {
url: "api/equipment_types",
type: "GET",
data: {
//"equipment_category": 1
},
dataType: "json"
}
},
schema: {
data: "data",
total: "total",
model:{
id: "name"
}
},
filter: { field: "used", operator: "neq", value: true }
});
I would suggest a different approach. Instead of removing the element filter it out.
Example: I define a DataSource with a list of Cities (your Inserted Equipment) as follow:
var cityDS = new kendo.data.DataSource ({
data : [
{ City : "Seattle", used : false },
{ City : "Tacoma", used : false },
{ City : "Kirkland", used : false },
{ City : "Redmond", used : false },
{ City : "London", used : false },
{ City : "Philadelphia", used : false },
{ City : "New York", used : false },
{ City : "Boston", used : false }
],
schema : {
model : {
id : "City"
}
},
filter: { field: "used", operator: "eq", value: false }
});
As you can see I added a field called used that simply says if that City is already used or not. And I set it as id of this DataSource. In addition, I set a filter saying that I only want those where used id equal (eq) to false.
The editor function is pretty much yours:
function cityDropDownEditor(container, options) {
var equipmentComboBox = $('<input required data-text-field="City" data-value-field="City" data-bind="value:' + options.field + '"/>')
.appendTo(container)
.kendoComboBox({
autoBind: false,
dataSource: cityDS
});
}
but with no dataBound or any other event handler.
Finally in the Grid when I save a record, I filter that city from the list. Something like:
var grid = $("#grid").kendoGrid({
dataSource: ds,
editable : "popup",
pageable : true,
toolbar: [ "create" ],
columns :
[
{ field: "FirstName", width: 90, title: "First Name" },
{ field: "LastName", width: 200, title: "Last Name" },
{ field: "City", width: 200, editor : cityDropDownEditor }
],
save : function(e) {
console.log("e", e);
var city = e.model.City;
cityDS.get(city).used = true;
}
}).data("kendoGrid");
This might work if you start the Grid with no elements otherwise you would have to conveniently initialize the used field. It might require some additional code dealing with cases as changing the City but from your description, doesn't seem to be the case.
You can see this running here : http://jsfiddle.net/OnaBai/ZH4aD/