My local JSON file contains documents (ending in .docx, .pdf, etc). I have a table that's rendering those documents and I want to be able to render the text '.docx' (and what not) into a separate column, with each text string corresponding to a document. The end goal is to replace the texts with their respective icons, i.e. a MS Word one for .docx.
So far I have an .includes('docx' || 'DOCX' || 'pptx') method that correctly shows the values as true and false in the table's column:
|true||Example.docx|
|false||Other.popx|
How can I include a loop (or something else) in the code I have to display the texts of 'docx', 'pptx', etc. instead of true and false?
Loading doc title data:
loadTableData() {
$.noConflict();
let tableRes = KMdocs.d.results.filter(function(val) {
return (val.FileLeafRef.trim().length > 0);
}).map(function(obj) {
return {
"Path": obj.EncodedAbsUrl,
"Titles": obj.File.Name,
"Categories": obj.ResourceType.results.map(function(val) {
return val.Label;
}).join(";"),
"Blank": "",
"docImg": obj.File.Name.includes('docx' || 'DOCX' || 'pptx')
// ----- this is where I'd like to include the code
}
})
Rendering table data:
$('#km-table-id').DataTable( {
columns: [
// { data: "Blank" },
{ data: "Categories" }, // hidden
{ data: "docImg" },
{ data: "Titles" } // must be in last position to respond w/ checkboxes
],
columnDefs: [
...etc
This will filter for docx and pptx and then return the value if it's provided
function documentType(fileName) {
return [fileName].filter(function(filter) {
return filter.toLowerCase().includes('docx') || filter.toLowerCase().includes('pptx')
}).map(function(filename) {
//Get File Extension
return filename.split('.').pop();
}).pop();
}
Usage would be:
"docImg": documentType(obj.File.Name)
I was task to add additional feature that can save its state after a user toggle the legend items when he logged out and the state should be the same when he logged in. Is it possible to do it in amchart?
AmCharts doesn't provide any built-in solutions to save/load chart state, so you need to write your own custom code. As #Abhijit mentioned, you can use localStorage to accomplish this. I already provided a sample solution in our support forum using the legend events but here it is again for you and anyone else who is looking:
AmCharts.makeChart("...", {
// ...
graphs: [{
// ...
//get hidden value from localStorage. needs to cast stored string "1" or "0" to a number, then casted to a boolean if a value exists
hidden:
localStorage.carsHidden !== undefined
? !!+localStorage.carsHidden
: false,
},
// repeat
],
legend: {
// ...
listeners: [
{
event: "showItem",
method: saveState
},
{
event: "hideItem",
method: saveState
}
]
}
});
function saveState(e) {
localStorage[e.dataItem.valueField + "Hidden"] =
e.type === "hideItem" ? 1 : 0;
}
Demo
I have autoGroupColumnDef and I want to setup text filter. But values of the column come from getDataPath method. But I need another value in the filter.
autoGroupColumnDef: {
headerName: "Systems",
filter: 'text',
valueGetter: function(params) {
var result = params.data.hospName || params.data.hospitalSystem;
return result;
},
cellRendererParams: {
suppressCount: true,
innerRenderer: function(params) {
var result = params.data.hospName || params.data.hospitalSystem;
return result;
}
}
},
After trying on couple of things,
Option 1: You can make use of [filterParams][1]. This only helps to play around with options/choices in the filterMenu..
function filterCellRenderer(params) {
//other than params.value nothing else will be there..
// params.data won't be there when its called from filter popup
return params.value+" Custom";
}
var gridOptions= {
...,
treeData: true,
components: {
...,
filterCellRenderer: filterCellRenderer
},
autoGroupColumnDef: {
...,
filterParams: {
cellRenderer: 'filterCellRenderer',
//values: ["A", "XYZ"] //you can feed directly specific values. These need to be part of filePath. Else filtering won't work.
}
}
}
Option 2: If you are looking for custom filter (tweak with GUI), or you want to post processing after it has been configured by ag-grid you can define the following:
var gridOptions = {
...
getMainMenuItems: getMainMenuItems,// function to build your own menu
postProcessPopup: function(params){
// edit the popup..
//params.type gives whether its column menu or not.
//params.ePopup gives handler to popup which you can modifiy.
},
...
}
OR you can build your own custom filter as described here
Following are the columns of my table, i got just this part of the code
products: {
title: 'Prodotto',
filter: false,
class: "colonneTabella",
width: "15%",
valuePrepareFunction: (products) => {
var output ="";
var outputs = "";
products.forEach(function(item){
output = item.productDescription
/* item.variantList.forEach(function(d){
outputs= d.description;
})*/
})
return output+outputs;
}
},
products: {
title: 'Variante',
filter: false,
class: "colonneTabella",
width: "20%",
valuePrepareFunction: (products) =>
products.forEach(function(item){
item.variantList;
item.variantList.forEach(function(d){
outputs= d.description;
})
return outputs;
})
}
Hi all! I'm in the above situation. I need to get datas from a json starting from the "products" key. The problem is that ng2 smart table doesn't allow columns with the same name. I tried, then, to rename the second column with "product.variantList" but the code doesn't accept dot inside the name. Is there any solution? thanks
There was similar problem reported when code breaks if dash ("-") is used in the key. Same solution will apply when dot (".") appears in the key.
Refer to - Reading out JSON using JavaScript
I'm wanting to disable an option if it has already been selected in one of the object groups.
So, if I selected "2013" then added another sample, "2013" would not be available in that group, unless that option is changed in the original group.
Is there an easy way to do this that I'm missing? Do I need to reactively update the schema when a selection is made?
samples:{
type: Array,
optional: true,
maxCount: 5
},
"samples.$":{
type: Object,
optional: true
},
"samples.$.sample":{
type:[String],
autoform: {
type: "select",
options: function () {
return [
{
optgroup: "Group",
options: [
{label: "2013", value: 2013},
{label: "2014", value: 2014},
{label: "2015", value: 2015}
]
}
];
}
}
},
Proof of Concept
I know this post is about 3 years old. However, I came across the same issue and want to provide an answer for all those who also stumbled over this post.
This answer is only a proof of concept and does not provide a full generic and performant solution, that could be used on production apps.
A fully generic solution would require a deep change in the code of how select field options are generated and updated in AutoForm.
Some prior notes.
I am using Autoform >=6 which provides a good API to instantly obtain field and form values in your SimpleSchema without greater trouble. SimpleSchema is included as npm package and Tracker has to be passed to it in order to ensure Meteor reactivity.
Functions like AutoForm.getFieldValue are reactive, which is a real great improvement. However, reactively changing the select options based on a reactive value causes a lot of update cycles and slows the performance (as we will see later).
Using AutoForm.getFormValues is not working, when using it within options of an Object field. While working within Array field, it will not behave reactively in Object fields, thus not update the filtering on them.
Manipulating Options for Arrays of Select Inputs (failing)
You can't use it with array types of fields. It's because if you change the select options, it applies for all your select instances in the array. It will therefore also apply to your already selected values and strips them away, too. This makes your select looks like it is always "not selected"
You can test that yourself with the following example code:
new SimpleSchema({
samples:{
type: Array,
optional: true,
maxCount: 5
},
"samples.$":{
type: String,
autoform: {
type: "select",
options: function () {
const values = AutoForm.getFormValues('sampleSchemaForm') || {};
const samples = values && values.insertDoc && values.insertDoc.samples
? values.insertDoc.samples
: [];
const mappedSamples = samples.map(x => x.sample);
const filteredOpts = [
{label: "2013", value: "2013"},
{label: "2014", value: "2014"},
{label: "2015", value: "2015"}
].filter(y => mappedSamples.indexOf(y.value) === -1);
return [
{
optgroup: "Group",
options:filteredOpts,
}
];
}
}
},
}, {tracker: Tracker});
Using fixed values on an Object Field
when taking a closer look at the schema, I saw the maxCount property. This made me think, that if you anyway have a list of max options, you could solve this by having fixed properties on a samples object (by the way: maxCount: 5 makes no sense, when there are only three select options).
This causes each select to have it's own update, that does not interfere the others. It requires an external function, that keeps track of all selected values but that came out be very easy.
Consider the following code:
export const SampleSchema = new SimpleSchema({
samples:{
type: Object,
optional: true,
},
"samples.a":{
type: String,
optional:true,
autoform: {
type: "select",
options: function () {
const samples = AutoForm.getFieldValue("samples");
return getOptions(samples, 'a');
}
}
},
"samples.b":{
type: String,
optional:true,
autoform: {
type: "select",
options: function () {
const samples = AutoForm.getFieldValue("samples");
return getOptions(samples, 'b');
}
}
},
"samples.c":{
type: String,
optional:true,
autoform: {
type: "select",
options: function () {
const samples = AutoForm.getFieldValue("samples");
return getOptions(samples, 'c');
}
}
},
}, {tracker: Tracker});
The code above has three sample entries (a, b and c) which will let their options be computed by an external function.
This function needs to fulfill certain requirements:
filter no options if nothin is selected
filter not the option, that is selected by the current samples select
filter all other options, if they are selected by another select
The code for this function is the following:
function getOptions(samples={}, prop) {
// get keys of selections to
// determine, for which one
// we will filter options
const sampleKeys = Object.keys(samples);
// get sample values to
// determine which values
// to filter here
const sampleValues = Object.values(samples);
const filteredOptiond = [
// note that values are stored as strings anyway
// so instead of parsing let's make them strings
{label: "2013", value: "2013"},
{label: "2014", value: "2014"},
{label: "2015", value: "2015"}
].filter(option => {
// case 1: nothing is selected yet
if (sampleKeys.length === 0) return true;
// case2: this selection has a
// selected option and current option
// is the selected -> keep this option
if (sampleKeys.indexOf(prop) > -1 && option.value === samples[prop])
return true;
// case 3: this selection has no value
// but others may have selected this option
return sampleValues.indexOf(option.value) === -1;
});
return [
{
optgroup: "Group",
options: filteredOptiond,
}
]
};
Some Notes on this Concept
Good:
-it works
-you can basically extend and scale it to your desired complexity (optgroups, more fields on samples, checking against other fields with other fields etc.)
Bad:
- performance
- bound to a given (or the nearest) form context (see here)
- much more code to write, than for an array.