Primevue Datatable Select Row Programmatically in Multiple Mode - vue.js

I am using PrimeVue Datatable with multiple selection checkboxes.
I need to implement the option to add a new row to the table and then select it automatically after adding it.
My problem is that pushing the added value to the selected rows array is not selecting it.
Template:
<DataTable :rows="10" :value="items" v-model:selection="selectedRows" dataKey="id"
responsiveLayout="scroll" v-model:filters="filters" #rowSelect="onRowSelect"
#rowUnselect="onRowUnselect" :row-hover="true">
<Column selectionMode="multiple" headerStyle="width: 3em"></Column>
<Column field="label" :header="translation.money.serviceName">
</Column>
</DataTable>
Function calling on Item Select and when new Item is added (isNew = true)
const onRowSelect = (event, isNew = false) => {
const selectedItem = event.data ?? event;
if (isNew) {
selectedRows.value.push(selectedItem );
}
};

Related

Update Datatables column searching dropdownbox after ajax load

I added a filtering function with Individual column searching (https://datatables.net/examples/api/multi_filter_select.html) to my datatable which is working fine.
This table also has a button to reload table data. The button triggers code like:
table.ajax.url("foo").load();
It updates table data correctly. Now, I want to update searching dropdown box with new column data. I want to empty dropdown box something like select.empty() then fill the box, but not sure how. I think this update process should be written in "rowCallback".
Summary
To rebuild the drop-downs after each ajax call, here is one approach:
Instead of using the DataTables ajax option, you can fetch the data using a jQuery ajax call, outside of DataTables.
Use the jQuery done function populate the table, and re-build the drop-downs after each ajax call.
This approach ensures that the ajax data has been fetched before any additional processing takes place.
Walkthrough
Assume we have a button like this:
<button type="button" onclick="fetchData();">Reload Data</button>
And a HTML table like this:
<table id="example" class="display" style="width:100%">
<tfoot>
<tr>
<th></th>
<th></th>
<th></th> <!-- you may need more footer cells in your table -->
</tr>
</tfoot>
</table>
Here is the related fetchData function, which clears all existing data, then re-populates the table with the newly fetched data:
function fetchData() {
$.ajax({
url: [your url goes here], // your URL here
context: document.body
}).done(function( data ) {
var table = $('#example').DataTable();
table.clear();
table.rows.add(data);
buildSelectLists();
table.draw();
});
}
The function to rebuild the select lists is identical to the logic from the DataTables example solution:
function buildSelectLists() {
$('#example').DataTable().columns().every(function() {
var column = this;
var select = $('<select><option value=""></option></select>')
.appendTo($(column.footer()).empty())
.on('change', function() {
var val = $.fn.dataTable.util.escapeRegex(
$(this).val()
);
column
.search(val ? '^' + val + '$' : '', true, false)
.draw();
});
column.data().unique().sort().each(function(d, j) {
select.append('<option value="' + d + '">' + d + '</option>')
});
});
}
Finally, the DataTable is defined in a "document ready" function:
$(document).ready(function() {
$('#example').DataTable({
// your options here - but no need for the ajax or data options
"initComplete": function() {
fetchData(); // make sure the table contains data, when it is created
}
});
});
Alternatively:
You can achieve a similar result by using the DataTables ajax option which makes use of a function:
Example (taken from the documentation here):
$('#example').dataTable( {
"ajax": function (data, callback, settings) {
callback(
JSON.parse( localStorage.getItem('dataTablesData') )
);
}
} );
I think in this case, it is a bit cleaner to keep the ajax call in its own separate function.

React Native: Checkbox List Structure

A user object has an array prop schools that references one or more school objects. I would like to use a <List> with <CheckBox> to mutate the schools array.
I load the user object into the view, and I load the listOfSchools (from the application state) to generate the checkbox list:
<List data={listOfSchools} keyExtractor={ item=> item._id } renderItem={({item})=>renderItem(item)} />
The renderItem function:
const renderItem = (school) => {
return <ListItem
title={school.name}
accessory={()=>renderAccessory(school)}
/>
};
The renderAccessory function:
const renderAccessory = (school) => {
return <CheckBox checked={() => checkSchool(school._id)} onChange={()=>changeSchool(school._id)} />
}
The checkSchool function returns boolean on if the school._id is referenced in the user.schools array. The changeSchool function adds or removes the school._id from the users.schools array.
The changeSchool function:
const changeSchool = (schoolId) => {
let checked = checkSchool(schoolId);
if (!checked) {
// add schoolId to user.schools
} else {
// remove schoolId from user.schools
}
}
This drastically does not work. It appears that no matter what I use to mutate the state, the checkboxes never update, nor does the user.schools array mutate.
What is the proper way to structure such a design goal?
Assuming that you use UI Kitten, I can see that you got the checked prop value wrong for the CheckBox component.
UI Kitten CheckBox reference
The checked prop needs to be a boolean not a Callable as you have it there
I would try to change the code like this:
const renderAccessory = (school) => {
const isChecked = checkSchool(school._id);
return <CheckBox checked={isChecked} onChange={()=>changeSchool(school._id)} />
}
Let me know if that helped.
While trying various solutions i can conclude few things here:
With the solution given by #Cornel Raiu the checked and unchecked flags are getting correctly calculated however, the display was not correct with the state of checked/unchecked
I replaced Checkbox with Toggle, just to be sure that it works with iOS too
PROBLEM that i faced still is that, even the State of item getting toggled is correctly populating it was getting reset
The outside container of Toggles is List and ListItem,
OBSERVATION is that the Press event on List was actually getting the Checkbox/Toggle into correct Display State...
SOLUTION:
After longer time of research and experiments I got my thing working with following approach -
I maintained separate collection of Checked Items
There is already a state of Collection of master items, as input to List
Every time the Checkbox/Toggle is clicked, the master list of Data is cloned and copied back to its state
This was triggering the slight re-render of component and thing is working as expected.
const [cashTransactions, setCashTransactions] = useState([]); // master data
const [selectedTransactions, setSelectedTransactions] = useState([]); // selected data
const renderItem = ({ item, index }) => (
<ListItem
title={'('+item.id + ') ' + item.firstName + ' ' + item.lastName}
description={Moment(item.createdOn).format('yyyy-MM-DD hh:mm:ss')}
accessoryLeft={selectedTransactions.includes(item.id) ? RadioOnIcon : RadioOffIcon}
accessoryRight={() => checkBoxSpace(item)}
/>
);
const checkBoxSpace = (item) => {
let itemChecked = selectedTransactions.includes(item.id);
return (
<View style={styles.actionContainer}>
<Button size='tiny' status='basic' accessoryLeft={rupeeSymbol}>{item.amount}</Button>
<Toggle checked={itemChecked} status='primary' size='small' onChange={checked => checkboxChecked(item, checked)}></Toggle>
</View>
)
}
const checkboxChecked = (item, checked) => {
console.log('Item -' + item.id + ' ' + checked);
if (checked) {
if (!selectedTransactions.includes(item.id)) {
selectedTransactions.push(item.id);
}
} else {
if (selectedTransactions.includes(item.id)) {
selectedTransactions.pop(item.id);
}
}
console.log('selectedTransactions ' + JSON.stringify(selectedTransactions));
// This is the thing i applied to get it done.
const cloned = [...cashTransactions];
setCashTransactions(cloned);
}
// View
<List
style={styles.container}
data={cashTransactions}
renderItem={renderItem}
/>

Vue: Why aren't list's items responsive?

I have a list of items that I pass to the component as props. Then I want to create a computed list mapped on the props list. What I do:
computed: {
assets: function(){
var self = this;
var mappedList = [];
if (self.sourceList && self.sourceList.length){
mappedList = _.map(self.sourceList, function(asset){
return { title: asset.title, id: asset.id};
});
}
return mappedList;
}
}
I can see the mapped list then rendered:
<div v-for="asset in assets" :key="asset.id">
<span>{{asset.title}}</span>
<input v-model="source.title" />
</div>
I can't figure out why but when I change a title it's not changed for the item is being edited.
(If I try just create a new list and use push method to add items into it, the result is the same).
UPD Solution found. As #WW noted some data should be used. I just move the list to the data and watch props and it worked.

Editing the selected option in the select dropdown(<q-select> of quasar framework)

I am trying the edit the previously selected option in the select drop down.I am able to show the checked options based on the data driven from the service call, but not able to choose other select option in the drop down.I am using quasar framework and vue.js.
Code:
<q-select
multiple
stack-label="Actions"
v-model="multiSelect"
:options="options"/>
Script:
import {QCheckbox,QSelect} from 'quasar'export
default {components: {QCheckbox,QSelect},
data () {return {
multSelect: [],
options1: [{label: 'X-B',value: 'x-b'},{label: 'RT-Builder',value: 'rt-builder'},{label: 'Com',value: 'com'},{label: 'Max',value: 'max'},{label: 'Runner',value: 'runner'},{label: 'Opto',value: 'opto'}],
....................
created () {
axios.get('http://*********/getDetails').then(response => {
this.multiSelect = response.data
})
}
Can someone help me with this?
The value you store in your component property multiSelect should be an array of the selectable values you want to be checked:
For example (following your data set):
this.multiSelect = ['x-b', 'rt-builder', 'max']
Whereas for "simple" select fields (single choice)
<q-select ... v-model="selectedValue" :options="options" />
you simply do
this.selectedValue = 'identifier'

Kendo DropDownListFor in EditorTemplate

I am creating a Dynamic Kendo Grid using GridBoundColumnBuilder().
I loop through all of the controls on the previous page to create the grid.
For example with myTextbox(), myCheckbox(), etc.
These create columns in the grid. I have all of the columns creating and populating with data.
My issue is with the Dropdownlist and the Multiselect list, they populate with data but do not display the correct data when the grid is created.
The dropdown list displays the value, not the text of the previous control:
1 = My
2 = Data
The Dropdownlist will display 1 instead of My. And, the Multiselect only displays [object Object].
When you click on either of the controls in the grid it switches to show the proper text, but loses it when you click off.
Any ideas of what I am doing wrong?
foreach (ControlBase control in flatColumns)
{
GridBoundColumnBuilder<dynamic> thisColumn;
if (control.Lookups != null && control.Lookups.Any())
{
if (!control.IsMultiSelect){
thisColumn = column.Bound(control.ControlType, control.ColumnName).Title(control.Description);
thisColumn.EditorTemplateName("DropDownList");
thisColumn.Width(250);
}
else
{
thisColumn = column.Bound(control.ControlType, control.ColumnName).Title(control.Description);
thisColumn.EditorTemplateName("MultiDropDownList");
thisColumn.Width(250);
}
}
}
Dropdown Template
#(Html.Kendo().DropDownListFor(m => m).HtmlAttributes(new { #class = "form-control" })
.BindTo((IEnumerable) ViewData[currentColumn + "List"])
.DataTextField("Text")
.DataValueField("Value")
.ValuePrimitive(true)
.Text("Value")
Multiselect Templage
#(Html.Kendo().MultiSelectFor(m => m)
.HtmlAttributes(new { #class = "form-control" })
.BindTo((IEnumerable)ViewData[currentColumn + "List"])
.DataTextField("Text")
.DataValueField("Value")
Have you tried changing the .Text to display the Text rather than the Value?
.DataTextField("Text")
.DataValueField("Value")
.ValuePrimitive(true)
.Text("Text")