vue - Bootstrap-vue: Select row (primary-key) based on an object with the same key values - bootstrap-vue

how can I select each rows with the same values from a separate object?
<b-table
:items="CurrentObject"
:select-mode="selectMode"
ref="selectableTable"
selectable
#row-selected="onRowSelected"
primary-key="uniqueID"
>
CurrentObject:
[
{name: 'A', uniqueID: 123, text: 'lorem ipsum'},
{name: 'B', uniqueID: 456, text: 'lorem ipsum'},
{name: 'C', uniqueID: 789, text: 'lorem ipsum'},
]
Separate Object:
[
{uniqueID: 123},
{uniqueID: 456},
{uniqueID: 789},
]

Using JavaScript's array.findIndex() and VueBootstrap's selectRow() seem to do it.
Template:
<template>
<b-container>
<div>
<h1>Current Object</h1>
<b-table
:items="currentObject"
:select-mode="selectMode"
ref="selectableTable"
selectable
#row-selected="onRowSelected"
primary-key="uniqueID"
>
</b-table>
<h2>Separate Object</h2>
<div v-for='object in separateObject' #click='selectMyRow(object.uniqueID);'>{{ object.uniqueID }}</div>
</div>
</b-container>
</template>
Script:
<script lang="ts">
import { Vue } from 'vue-property-decorator';
export default class HelloWorld extends Vue {
selectMode = 'single';
currentObject = [
{name: 'A', uniqueID: 123, text: 'lorem ipsum'},
{name: 'B', uniqueID: 456, text: 'lorem ipsum'},
{name: 'C', uniqueID: 789, text: 'lorem ipsum'},
];
separateObject = [
{uniqueID: 123},
{uniqueID: 456},
{uniqueID: 789},
];
selectMyRow(uniqueID) {
const row = this.currentObject.findIndex(x => x.uniqueID === uniqueID);
this.$refs.selectableTable.selectRow(row);
}
onRowSelected() {
// do something else
}
}
</script>
Working example:
If instead, you need similar functionality using select-mode multi, use the following:
selectMode = 'multi';
...
selectMyRow(uniqueID) {
const row = this.currentObject.findIndex(x => x.uniqueID === uniqueID);
const table = this.$refs.selectableTable
if (table.isRowSelected(row)) {
table.unselectRow(row);
} else {
table.selectRow(row);
}
}

OK, I have the first solution for me.
I couldn't update the jsfiddle yet ...
I have 2 watch functions, each with a for loop
the first loop checks whether in separateArray
var TableStore = this.TableStore; // -> ARRAY NO OBJECT
for (var i = 0; i < TableStore.length; i++) {
const row = this.CurrentArray.findIndex(x => x.unID === TableStore[i]);
this.$refs.selectableTable.selectRow(row);
}
the second checks whether not.
(filter / includes -> CurrentArray - SeparateArray)

Related

How to create reactive search input field in Vue.js?

I want to build a seach input field that sorts an object array while typing, using vue 3 with script setup.
input field:
<input type="search" placeholder="Search" v-model="state.search">
script setup:
const state = reactive({
search: ''
})
const array = [
{id: 1, title: 'Valhalla', content: '123'},
{id: 2, title: 'Wurstopia', content: '456'},
{id: 3, title: 'Brandon', content: '789'}
]
const search = computed(() => {
// sort array reactively according to search (use title as sorting criteria)
const result = sort(array['title'], state.search)
})
Is using computed the right approach for this? How do I reactively sort the array for search input ~ title?
If making this reactive is a problem, I am also happy with an approach of just submitting the input and sorting the array afterwards.
Edit:
I've tried the approach of #AdriHM but it produces exactly the same unsorted array:
const state = reactive({
search: '',
array: [
{id: 1, title: 'Valhalla', content: '123'},
{id: 2, title: 'Wurstopia', content: '456'},
{id: 3, title: 'Brandon', content: '789'}
]
})
function mySort(searchKey){
let matchedKeys = [], notMatchedKeys = [];
for(let i = 0; i < state.array.length; i++) {
if (state.array[i]['title'].match(searchKey) ) {
matchedKeys.push(state.array[i])
} else{
notMatchedKeys.push(state.array[i])
}
}
}
console.log(mySort(state.search))
Output:
(3) [Proxy, Proxy, Proxy]
0: Proxy {id: 1, title: 'Valhalla', content: '123'}
1: Proxy {id: 2, title: 'Wurstopia', content: '456'}
2: Proxy {id: 3, title: 'Brandon', content: '789'}
length: 3
[[Prototype]]: Array(0)
If what you want to do is a sort you can do it like this:
<template>
<input type="search" placeholder="Search" v-model="state.search">
{{ state.array }}
</template>
<script lang="ts" setup>
import {reactive, watch} from "vue";
const state = reactive({
search: '',
array: [
{id: 1, title: 'Valhalla', content: '123'},
{id: 2, title: 'Wurstopia', content: '456'},
{id: 3, title: 'Brandon', content: '789'}
]
})
function mySort(searchKey: string){
let matchedKeys = [], notMatchedKeys = [];
for(let i = 0; i < state.array.length; i++) {
if (state.array[i]['title'].match(searchKey) ) {
matchedKeys.push(state.array[i])
} else{
notMatchedKeys.push(state.array[i])
}
}
return matchedKeys.concat(notMatchedKeys);
}
watch(() => state.search, () => {
// sort of filter
state.array = mySort(state.search)
})
</script>
It will only put at first position the element that match the query but you have the logic to make the array changing with watch.
If I understand correctly, the objective is to filter an array by a search term, and display the results sorted by title.
The sorting itself does not need to be reactive because the array is always sorted by title. The array can be sorted once, and then the sorted array can be filtered reactively in the computed prop.
Use Array.prototype.sort() to sort array[] by the title field.
In the computed prop, use Array.prototype.filter() to include only items whose title or content field contains state.search. filter() does not change the order of the results, so no additional sorting is needed.
<script setup>
import { reactive, computed } from 'vue'
const state = reactive({
search: '',
})
const array = [
{ id: 1, title: 'Valhalla', content: '123' },
{ id: 2, title: 'Wurstopia', content: '456' },
{ id: 3, title: 'Brandon', content: '789' },
]
1️⃣
array.sort((a, b) => a.title.localeCompare(b.title))
const results = computed(() => {
2️⃣
return array.filter(item => item.title.includes(state.search) || item.content.includes(state.search))
})
</script>
demo

How to remove object from axios proxy array

The below is slightly simplified...
The Axios request returns data like this:
Proxy {0: {…}, 1: {…}, 2: {…}}
[[Handler]]: Object
[[Target]]: Array(3)
0: {code: "AAA", id: "001", label: "Foo"}
1: {code: "BBB", id: "002", label: "Bar"}
2: {code: "CCC", id: "003", label: "Baz"}
I am trying to remove any objects from this which match items in my array:
var reqData = this.requestData;
var myArr = ["Foo", "Bar"];
for (let index = 0; index < myArr.length; ++index) {
reqData = reqData.filter(function( obj ) {
return obj.label !== myArr[index];
});
}
This works, to a degree. It produces the following:
(1) [Proxy]
0: Proxy {code: "CCC" id: "003", label: "Baz"}
However this data does not output in the vue HTML. I notice the structure has changed and no longer shows Handler and Target.
Push the reqData items to an array
var testarr = [];
for (let index = 0; index < reqData.length; ++index) {
testarr.push({label: reqData[index].label, id: reqData[index].id, code: reqData[index].code });
}
rebuild proxy object
var proxy = new Proxy( testarr, {} );

ag-Grid, try to make Tree Demo work using own data

I like the ag-Grid because it's less buggy, fast and works with many frameworks.
So I tried the Tree Data, no need to tell the link between parents and children, simply lay down the data in structure, specify some options, Bingo! But, when I plug in my API, it tells me
"TypeError: rowData is undefined"
from inside of ag-grid.js even though Watch clearly shows it has the array. There are some answered Question here regarding customization with internal api. Mine is not.
I then use the official demo as a base, set up a Fiddler to grab the raw data in JSON replace demo data to make it hardcoded for a test to determine if it's problem with own API or something else. Here is the Plunker. Note it's totally based on the official javaScript Demo of Tree Data, Tree Data Example, the first one.
In case you don't want to see Plunker, here is my .js:
var columnDefs = [
{headerName: "Client", field: "Client", cellRenderer: 'group'},
{headerName: "Program", field: "Program"}
/*{headerName: "Group", field: "xgroup", cellRenderer: 'group'}, // cellRenderer: 'group'}, -- this "group" is one of the default value option for built-in cellRenderer function, not field.
//{headerName: "Athlete", field: "athlete"},
//{headerName: "Year", field: "year"},
{headerName: "Country", field: "country"}
*/
];
var myData = [
{
'Client': 'Goodle',
'Program': 'no grid',
'kids': []
},
{
'Client': 'Facebrook',
'Program': 'grids',
'kids': [
{
'Client': 'Facebrook',
'Program': 'ag-Grid'
},
{
'Client': 'Facebrook',
'Program': 'ui-grid'
}
]
}
/*{xgroup: 'Group A',
participants: [
/*{athlete: 'Michael Phelps', year: '2008', country: 'United States'},
{athlete: 'Michael Phelps', year: '2008', country: 'United States'},
{athlete: 'Michael Phelps', year: '2008', country: 'United States'}*/
/*]},
{xgroup: 'Group B', athlete: 'Sausage', year: 'Spaceman', country: 'Winklepicker',
participants: [
{athlete: 'Natalie Coughlin', year: '2008', country: 'United States'},
{athlete: 'Missy Franklin ', year: '2012', country: 'United States'},
{athlete: 'Ole Einar Qjorndalen', year: '2002', country: 'Norway'},
{athlete: 'Marit Bjorgen', year: '2010', country: 'Norway'},
{athlete: 'Ian Thorpe', year: '2000', country: 'Australia'}
]},
{xgroup: 'Group C',
participants: [
{athlete: 'Janica Kostelic', year: '2002', country: 'Crotia'},
{athlete: 'An Hyeon-Su', year: '2006', country: 'South Korea'}
]}*/
];
var gridOptions = {
columnDefs: columnDefs,
rowData: myData,
rowSelection: "single",
enableSorting: "true", unSortIcon: "true",
enableColResize: "true",
enableRangeSelection: "true",
suppressCellSelection: "false",
showToolPanel: "true",
supressCopyRowsToClipboard: true,
supressCellSelection: false,
getNodeChildDetails: getNodeChildDetails,
onGridReady: function(params) {
params.api.sizeColumnsToFit();
}
};
function getNodeChildDetails(rowItem) {
if (rowItem.Client) {
return {
group: true,
// open C be default
//expanded: rowItem.ClientName === 'Group C',
// provide ag-Grid with the children of this group
children: rowItem.kids,
// this is not used, however it is available to the cellRenderers,
// if you provide a custom cellRenderer, you might use it. it's more
// relavent if you are doing multi levels of groupings, not just one
// as in this example.
//field: 'group',
// the key is used by the default group cellRenderer
key: rowItem.Client
};
} else {
return null;
}
}
function onFilterChanged(value) {
gridOptions.api.setQuickFilter(value);
}
// setup the grid after the page has finished loading
document.addEventListener('DOMContentLoaded', function() {
var gridDiv = document.querySelector('#myGrid');
new agGrid.Grid(gridDiv, gridOptions);
});
HTML:
<html>
<head>
<!-- you don't need ignore=notused in your code, this is just here to trick the cache -->
<script src="https://ag-grid.com/dist/ag-grid/ag-grid.js"></script>
<script src="script.js"></script>
</head>
<body>
<input placeholder="Filter..." type="text"
onpaste="onFilterChanged(this.value)"
oninput="onFilterChanged(this.value)"
onchange="onFilterChanged(this.value)"
onkeydown="onFilterChanged(this.value)"
onkeyup="onFilterChanged(this.value)"/>
<div id="myGrid" class="ag-fresh" style="height: 450px; margin-top: 4px;"></div>
</body>
</html>
Need some experts!
You need to alter getNodeChildDetails to have this:
function getNodeChildDetails(rowItem) {
if (rowItem.Client && rowItem.kids && rowItem.kids.length > 0) {
As you have it you're telling the grid that any item with Client is a parent node, but what you really mean in your data is any item with Client AND kids is a parent.
Remember that the grid can have multiple levels so a child can be a parent too.

how do i get a w2ui grid cell value?

i want to get my "id" value of w2ui grid. The record came from a database
columns: [
{ field: 'id', caption: 'ID', size: '50px' },
{ field: 'name', caption: 'Name', size: '300px'},]
my function
onDblClick: function (event) {
var grid = this;
event.onComplete = function () {
var sel = grid.getSelection();
console.log('my id value ' + sel.id);
}
but nothing appear. i do it wrong?
grid.getSelection() returns an array of selected recids, see the documentation.
You should change your code as follows:
$(function() {
$('#grid').w2grid({
name: 'grid',
columns: [
{ field: 'id', caption: 'ID', size: '50px' },
{ field: 'name', caption: 'Name', size: '300px' }
],
records: [
{ recid: 1, id: '1', name: 'Name 1' },
{ recid: 2, id: '2', name: 'Name 2' }
],
onDblClick: function(event) {
var grid = this;
event.onComplete = function() {
var sel_rec_ids = grid.getSelection();
if (sel_rec_ids.length) {
var sel_record = grid.get(sel_rec_ids[0]);
console.log('selected ID:', sel_record.id, '/ selected Name:', sel_record.name);
} else {
console.log("Nothing selected!");
}
}
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.0/jquery.min.js"></script>
<script src="https://rawgit.com/vitmalina/w2ui/master/dist/w2ui.js"></script>
<link href="https://rawgit.com/vitmalina/w2ui/master/dist/w2ui.css" rel="stylesheet" />
<div id="grid" style="width: 100%; height: 150px;"></div>
Also let me quote something, that some else commented on one of your questions in 2013:
I see you've not accepted any answer to your questions. That kinda defeats the goal of Stack Overflow. It would be great if you could review all the questions you've asked, accept correct answers and give feedback on proposed solutions that don't work

ion-autocomplete not displaying results case-sensitive

I am using ionic and using ion-autocomplete to display my list of items.
if i have my result array like this
var homeworksingle = [
{id: '1', name: 'Maths'},
{id: '2', name: 'English'},
{id: '3', name: 'Physics'}
];
<input ion-autocomplete type="text" readonly="readonly" class="ion-autocomplete" autocomplete="off" ng-model="model" item-value-key="id" item-view-value-key="name" items-method="getTestItems(query)" items-method-value-key="items" placeholder="Enter test query ..." items-clicked-method="itemsClicked(callback)" items-removed-method="itemsRemoved(callback)"/>
$scope.getTestItems = function (query) {
var homeworksingle = [
{id: '1', name: 'Maths'},
{id: '2', name: 'English'},
{id: '3', name: 'Physics'}
];
var returnValue = { items: [] };
homeworksingle.forEach(function(item){
if (item.name.indexOf(query) > -1 ){
returnValue.items.push(item);
}
else if (item.id.indexOf(query) > -1 ){
returnValue.items.push(item);
}
});
return returnValue;
};
and when i try to search my list nd input 'm', it returns no result but when i input 'M' it returns data.
How do i set it to also acknowledge or search when input is lowercase or uppercase.
Thanks