bootstrap-vue Custom data rendering sorting by item key (simpler than formatter) - bootstrap-vue

Using https://bootstrap-vue.org/docs/components/table#custom-data-rendering
would like to enable sorting on some columns, eg by "First name and age"
Docs say it's not possible to sort by custom rendered data, which is ok. For the "First name and age" column, I'd like to specify sortKey to be age field, which exists in items.
{ key: 'nameage', label: 'First name and age', sortable: true, sortKey: 'age' }
However, setting sortKey has no effect. Could this be accomplished, without using a custom formatter and sort/compare function?
Full code:
<template>
<div>
<b-table small :fields="fields" :items="items" responsive="sm">
<!-- A virtual column -->
<template #cell(index)="data">
{{ data.index + 1 }}
</template>
<!-- A custom formatted column -->
<template #cell(name)="data">
<b class="text-info">{{ data.value.last.toUpperCase() }}</b>, <b>{{ data.value.first }}</b>
</template>
<!-- A virtual composite column -->
<template #cell(nameage)="data">
{{ data.item.name.first }} is {{ data.item.age }} years old
</template>
<!-- Optional default data cell scoped slot -->
<template #cell()="data">
<i>{{ data.value }}</i>
</template>
</b-table>
</div>
</template>
<script>
export default {
data() {
return {
fields: [
// A virtual column that doesn't exist in items
'index',
// A column that needs custom formatting
{ key: 'name', label: 'Full Name' },
// A regular column
'age',
// A regular column
'sex',
// A virtual column made up from two fields
{ key: 'nameage', label: 'First name and age', sortable: true, sortKey: 'age' }
],
items: [
{ name: { first: 'John', last: 'Doe' }, sex: 'Male', age: 42 },
{ name: { first: 'Jane', last: 'Doe' }, sex: 'Female', age: 36 },
{ name: { first: 'Rubin', last: 'Kincade' }, sex: 'Male', age: 73 },
{ name: { first: 'Shirley', last: 'Partridge' }, sex: 'Female', age: 62 }
]
}
}
}
</script>

Related

Yadcf integrate with Meteor simple schema

I want to filter column header data from my tabular table.
My goal is to filter:
Numbers (greater than, equal etc...)
Strings
Dates
as in the following example
Thus I want to integrate the filters of yadcf with my tabular table by using the Orion schema, by I can´t conclude,
FIRST OPTION WITH SCHEMA
Mi schema
Tickets = new orion.collection('tickets', {
singularName: 'Tickets',
pluralName: 'Tickets',
title: 'Tickets',
parentPath: '/admin',
link: {title: 'Tickets', parent: '_template'},
tabular: {
scrollX: true,
"processing": true,
dom: 'lBfrtip',
columns: [
{ data: "id", title: "ID" },
{ data: 'employeeName', title: 'Name' }
]
}
});
Tickets.attachSchema(new SimpleSchema({
id: { type: Number, label:'Id del Empleado', optional: true },
employeeName: { type: String, label:'Name', optional: true }
}));
if (Meteor.isServer) {
Meteor.publish('get_Tickets', function() {return Tickets.find();});
};
if (Meteor.isClient) {
Meteor.subscribe('get_Tickets');
};
My.html
{{> tabular table=collection.tabularTable class="table table-striped bordered" id=collection.pluralName }}
SECOND OPTION WITH INSTANCE OF DATATABLE
my.js
var TicketsTab=new Tabular.Table({
name: 'Tickets',
collection: Tickets,
searching:true,
columns: [
{data: "id",title:"ID"},
{data: "employeeName",title:"Name"}
]
});
var myTable = $('#TicketsTab').DataTable();
yadcf.init(myTable, [{column_number:0}]);
In this point I can´t conclude because I don´t know how to add .dataTable().yadcf([...]);

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.

Validate Input of a Form Against Another Collection

I would like to validate the input of a form against the existence of common fields in another collection. Any suggestions on how to accomplish this?
Edit: Added code example and context
I have simply built this as a prototype infrastructure.
Schemas:
Transactions.schema = new SimpleSchema({
key: { // When inserted this need to be an existing key
type: Number,
unique: true,
min: 0,
max: 1000000000,
},
employee: { // When inserted this need to be an existing employee
type: String,
regEx: /^[0-9]+[NCV]$/,
min: 4,
max: 128,
},
});
Keys.schema = new SimpleSchema({
code: {
type: Number,
unique: true,
min: 0,
max: 1000000000,
},
name: {
type: String,
min: 3,
max: 128,
},
});
Employees.schema = new SimpleSchema({
empId: {
type: String,
regEx: /^[0-9]+[NCV]$/,
min: 4,
max: 128,
},
});
Currently, I'm simply using a validation and upsert method for ease of troubleshooting and experimenting.
export const upsertTransaction = new ValidatedMethod({
name: 'transactions.upsert',
validate: new SimpleSchema({
_id: { type: String, optional: true },
key: { type: Number, optional: true }, // I think this is where I need to validate existing key
employee: { type: String, optional: true }, // I think this is where I need to validate existing employee
}).validator(),
run(document) {
return Transactions.upsert({ _id: document._id }, { $set: document });
},
});
React form:
export default class TransactionEditor extends React.Component {
componentDidMount() {
transactionEditor({ component: this });
setTimeout(() => { document.querySelector('[name="key"]').focus(); }, 0);
}
render() {
const { trans } = this.props;
return (<form
ref={ form => (this.transactionEditorForm = form) }
onSubmit={ event => event.preventDefault() }
>
<FormGroup>
<ControlLabel>Key</ControlLabel>
<FormControl
type="number"
name="key"
defaultValue={ trans && trans.key }
placeholder="1234"
/>
</FormGroup>
<FormGroup>
<ControlLabel>Employee</ControlLabel>
<FormControl
type="text"
name="employee"
defaultValue={ trans && trans.employee }
placeholder="12345V"
/>
</FormGroup>
<Button type="submit" bsStyle="success">
{ trans && trans._id ? 'Save Changes' : 'Add Transaction' }
</Button>
</form>);
}
}
I'm using https://github.com/themeteorchef/base as a framework, for reference.

Error when load form data in W2UI. "Cannot associate field "id" with html control"

My form can not update data which it got from server to form's record.
Below is my w2form
$().w2form({
name: 'editSv',
method: 'GET',
style: 'border: 0px; background-color: transparent;',
recid: w2ui['grid'].records[w2ui['grid'].getSelection(true)]['id'],
url: {
get: '/api/Test/GetService/' + w2ui['grid'].records[w2ui['grid'].getSelection(true)]['id'],
save: '/api/Test/PostService'
},
formURL: '/api/Test/GetService/' + w2ui['grid'].records[w2ui['grid'].getSelection(true)]['id'],
fields: [
{ name: 'id', type: 'number', required: true },
{ name: 'servicename', type: 'text', required: true },
{ name: 'price', type: 'number', required: true },
{ name: 'unit', type: 'text' }
],
record: {
id: 0,
servicename: '',
price: 0,
unit: ''
}, onSubmit: function (formName, formObj) {
formObj.postData = formObj.postData.record;
},
onLoad: function (event) {
console.log(event.xhr);
},
actions: {
"save": function () {
var obj = this;
this.submit({}, function (data) {
if (data.status == 'success') {
w2alert(data.status);
w2ui['grid'].reload();
} else {
w2alert(data.message);
return;
}
obj.clear();
});
},
"reset": function () { this.clear(); },
}
});
This is data got from onLoad() event
{readyState: 4, responseText: "{"id":5,"servicename":"4","price":4.0000,"unit":"4"}", status: 200, statusText: "OK"}
And the message from chrome's console:
ERROR: Cannot associate field "id" with html control. Make sure html control exists with the same name.
ERROR: Cannot associate field "servicename" with html control. Make sure html control exists with the same name.
ERROR: Cannot associate field "price" with html control. Make sure html control exists with the same name.
ERROR: Cannot associate field "unit" with html control. Make sure html control exists with the same name.
I have tried to add formHTML to w2form but it makes no sense. Has anyone solved this problem?
Have you defined any HTML page for your w2ui form in this case you can use kickstart or you can define formHTML in your form:
$().w2form({
name: 'editSv',
style:'border: 0px',
focus:-1,method: 'GET',
style: 'border: 0px; background-color: transparent;',
recid: w2ui['grid'].records[w2ui['grid'].getSelection(true)]['id'],
url: {
get: '/api/Test/GetService/' + w2ui['grid'].records[w2ui['grid'].getSelection(true)]['id'],
save: '/api/Test/PostService'
},
formURL: '/api/Test/GetService/' + w2ui['grid'].records[w2ui['grid'].getSelection(true)]['id'],
formHTML:
'<div class="w2ui-page page-0">'+
' <div class="w2ui-field">'+
' <label> id </label>'+
' <div>'+
' <input name="id" type="text" />'+
' </div>'+
' </div>'+ ' <div class="w2ui-field">'+
' <label> id </label>'+
' <div>'+
' <input name="id" type="text" />'+
' </div>'+
' </div>'+ ' <div class="w2ui-field">'+
' <label> price </label>'+
' <div>'+
' <input name="price" type="text" />'+
' </div>'+
' </div>'+ ' <div class="w2ui-field">'+
' <label> unit </label>'+
' <div>'+
' <input name="unit" type="text" />'+
' </div>'+
' </div>'+
'<div class="w2ui-buttons">'+
' <button class="btn" name="Cancel">Cancel</button>'+
' <button class="btn" name="Save">Save</button>'+
'</div>',
fields: [
{ name: 'id', type: 'number', required: true },
{ name: 'servicename', type: 'text', required: true },
{ name: 'price', type: 'number', required: true },
{ name: 'unit', type: 'text' }
],
record: {
id: 0,
servicename: '',
price: 0,
unit: ''
}, onSubmit: function (formName, formObj) {
formObj.postData = formObj.postData.record;
},
onLoad: function (event) {
console.log(event.xhr);
},
actions: {
"save": function () {
var obj = this;
this.submit({}, function (data) {
if (data.status == 'success') {
w2alert(data.status);
w2ui['grid'].reload();
} else {
w2alert(data.message);
return;
}
obj.clear();
});
},
"reset": function () { this.clear(); },
}
});

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