I'm using jquery-querybuilder to build out a query. I'm currently having an issue with adding in selectize as a plugin to allow for autocomplete inside the select inputs. I'm logging the data in the for loop and it prints out the correct data so I know its physically getting the data, but when typing in the input box, there is still no autocomplete and I'm not quite sure where I went wrong.
let totalMachines = [];
var rules_basic = {
condition: 'AND',
rules: [{
}, {
condition: 'OR',
rules: [{
}, {
}]
}]
};
let options = {
plugins: [],
allow_empty: true,
filters: [
{
id: 'machineName',
label: 'Machine Name',
type: 'string',
input: 'text',
operators: ['equal'],
plugin: 'selectize',
values: {
},
plugin_config: {
valueField: 'id',
labelField: 'machineName',
searchField: 'machineName',
sortField: 'machineName',
create: false,
maxItems:3,
plugins: ['remove_button'],
onInitialize: function() {
var that = this;
totalMachines.forEach(function(item) {
that.addOption(item);
console.log(item)
});
}
},
valueSetter: function(rule, value) {
rule.$el.find('.rule-value-container input')[0].selectize.setValue(value);
}
},
]
}
$.ajax({
url: '/api-endpoint',
type: 'GET',
contentType: 'application/json',
dataType: 'json',
success: function(response){
console.log(response)
response.forEach((res) => {
totalMachines.push(res[0])
})
console.log(totalMachines)
}
})
.then(() => {
// Fix for Selectize
$('#builder').on('afterCreateRuleInput.queryBuilder', function(e, rule) {
if (rule.filter.plugin == 'selectize') {
rule.$el.find('.rule-value-container').css('min-width', '200px')
.find('.selectize-control').removeClass('form-control');
}
});
$('#builder').queryBuilder(options)
})
It would be extremely helpful if someone could help me figure out how to properly configure this plugin, I've looked at every thread and haven't been able to figure it out.
Here is a simple example, using a local datasource, the namesList array
<script>
$(document).ready(function() {
let namesList = [{ id: '1', name: 'andrew' }, { id: '2', name: 'bob' }, { id: '3', name: 'charles' }, { id: '4', name: 'david' }];
let pluginConfig = {
preload: true,
valueField: 'id',
labelField: 'name',
searchField: 'name',
options: namesList,
items: ['2'],
allowEmptyOption: true,
plugins: ['remove_button'],
onInitialize: function () { },
onChange: function (value) {
console.log(value);
},
valueSetter: function (rule, value) {
rule.$el.find('.rule-value-container input')[0].selectize.setValue(value);
},
valueGetter: function (rule) {
var val = rule.$el.find('.rule-value-container input')[0].selectize.getValue();
return val.split(',');
}
}
let filterList = [{
id: 'age',
type: 'integer',
input: 'text'
},
{
id: 'id',
label: 'name',
name: 'name',
type: 'string',
input: 'text',
plugin: 'selectize',
plugin_config: pluginConfig
}];
let options = {
allow_empty: true,
operators: ['equal', 'not_equal', 'greater', 'greater_or_equal', 'less', 'less_or_equal'],
filters: filterList
}
$('#builder').queryBuilder(options);
// Fix for Selectize
$('#builder').on('afterCreateRuleInput.queryBuilder', function (e, rule) {
if (rule.filter.plugin == 'selectize') {
rule.$el.find('.rule-value-container').css('min-width', '200px').find('.selectize-control').removeClass('form-control');
}
});
});
I've been dealing with creating an object with reduce from a nested array.
The object needs to have the _iud keys with the value of initialValue, from the object that contains both keys. I made a function that can iterate through them but can't return the new object with all the new properties I got. I've tried to use the shallow and deep copy to clone acc but can't make it :( Could anyone give me a hand?
This is the nested array
export const formData = [
{
component: 'page',
label: 'Page 1',
_uid: '0c946643-5a83-4545-baea-055b27b51e8a',
fields: [
{
component: 'field_group',
label: 'Name',
_uid: 'eb169f76-4cd9-4513-b673-87c5c7d27e02',
fields: [
{
component: 'text',
label: 'First Name',
initialValue: '2345432',
type: 'text',
_uid: '5b9b79d2-32f2-42a1-b89f-203dfc0b6b98',
},
{
component: 'text',
label: 'Last Name',
initialValue: '2345432',
type: 'text',
_uid: '6eff3638-80a7-4427-b07b-4c1be1c6b186',
},
],
},
{
component: 'text',
label: 'Email',
initialValue: '2345432',
type: 'email',
_uid: '7f885969-f8ba-40b9-bf5d-0d57bc9c6a8d',
},
{
component: 'text',
label: 'Phone',
initialValue: '2345432',
type: 'text',
_uid: 'f61233e8-565e-43d0-9c14-7d7f220c6020',
},
],
},
{
component: 'page',
label: 'Page 2',
_uid: '3a30803f-135f-442c-ab6e-d44d7d7a5164',
fields: [
{
component: 'options',
label: 'Radio Buttons',
type: 'radio',
initialValue: '2345432',
_uid: 'bd90f44a-d479-49ae-ad66-c2c475dca66b',
options: [
{
component: 'option',
label: 'Option 1',
value: 'one',
},
{
component: 'option',
label: 'Option 2',
value: 'two',
},
],
},
{
component: 'text',
label: 'Conditional Field',
type: 'text',
_uid: 'bd90f44a-d479-49ae-ad66-c2c475daa66b',
initialValue: '2345432',
conditional: {
value: 'two',
field: '3a30803f-135f-442c-ab6e-d44d7d7a5164_bd90f44a-d479-49ae-ad66-c2c475dca66b',
},
},
],
},
{
component: 'page',
label: 'Page 3a',
_uid: 'cd392929-c62e-4cdb-b4dd-914035c1cc8d',
initialValue: '2345432',
conditional: {
value: 'one',
field: '3a30803f-135f-442c-ab6e-d44d7d7a5164_bd90f44a-d479-49ae-ad66-c2c475dca66b',
},
fields: [
{
component: 'options',
label: 'More radio buttons',
type: 'radio',
_uid: 'a15bef56-ab67-4b98-a781-4441cc3bba56',
initialValue: '2345432',
options: [
{ component: 'option', label: 'Option 1', value: 'one' },
{ component: 'option', label: 'Option 2', value: 'two' },
],
},
],
},
{
component: 'page',
label: 'Page 3b',
_uid: '1dd4ec7c-fb53-47f4-af1b-1ab8f805b888',
conditional: {
value: 'two',
initialValue: '2345432',
field: '3a30803f-135f-442c-ab6e-d44d7d7a5164_bd90f44a-d479-49ae-ad66-c2c475dca66b',
},
fields: [
{
component: 'options',
label: 'Something to toggle',
type: 'radio',
_uid: '3ca9237d-e225-4950-a298-f81ce996cb85',
options: [
{
component: 'option',
label: 'Option 1',
value: 'one',
},
{ component: 'option', label: 'Option 2', value: 'two' },
],
},
{
component: 'field_group',
label: 'Name',
_uid: 'b8406cb5-ff0d-4a83-a8f8-99740b6d91f7',
fields: [
{
component: 'text',
label: 'First Name',
initialValue: '2345432',
type: 'text',
_uid: 'c6e065e1-dbcb-44ea-831f-ac3af889e964',
},
{
component: 'text',
label: 'Last Name',
initialValue: '2345432',
type: 'text',
_uid: 'e279ba9c-3c9b-4df8-b267-d14b3c2adcdd',
},
],
},
{
component: 'text',
label: 'Email',
initialValue: '2345432',
type: 'email',
_uid: 'a95208a0-7673-48a8-b704-2fb408fa6eec',
},
{
component: 'text',
label: 'Phone',
initialValue: '2345432',
type: 'text',
_uid: '8dde5083-0619-42d6-8fc7-0563c35d03ad',
},
],
},
{
component: 'page',
label: 'Page 4',
_uid: '0c946643-5a83-4545-baea-065b27b51e8a',
fields: [
{
component: 'text',
label: 'Final Comment',
initialValue: '2345432',
type: 'text',
_uid: 'f61231e8-565e-43d0-9c14-7d7f220c6020',
},
],
},
]
The function:
function getInitialValues(formData = []) {
return Array.from(formData).reduce((acc, currentValue, idx) => {
const arrayOfStrings = ['page', 'field_group', 'options']
const str = currentValue.component
const found = arrayOfStrings.find((v) => str === v)
if (found) {
// console.log('entro', currentValue)
getInitialValues(currentValue?.fields)
return acc
}
if (
(currentValue.component === 'text' || currentValue.component === 'select') &&
currentValue.label === 'Conditional Field'
) {
acc[currentValue._uid] = currentValue?.initialValue
return acc
}
return acc
}, {})
}
My expected result is something like this from all the _uids that has initialValues (only for references)
{
5b9b79d2-32f2-42a1-b89f-203dfc0b6b98: '2345432',
5b9b79d2-32f2-42a1-b89f-203dfc0b6b97: '2345431',
5b9b79d2-32f2-42a1-b89f-203dfc0b6b96: '2345430',
}
I find it easier to separate the extraction of your _uid/initialValue properties from the formatting of these into an output object.
Here is a recursive extract function and a simple convert function that builds on it.
const extract = (xs) =>
xs .flatMap (({initialValue, _uid, fields = []}) =>
[[_uid, initialValue], ...extract (fields)]
) .filter (([_, init]) => init != null)
const convert = xs =>
Object .fromEntries (extract (xs))
const formData = [{component: "page", label: "Page 1", _uid: "0c946643-5a83-4545-baea-055b27b51e8a", fields: [{component: "field_group", label: "Name", _uid: "eb169f76-4cd9-4513-b673-87c5c7d27e02", fields: [{component: "text", label: "First Name", initialValue: "2345432", type: "text", _uid: "5b9b79d2-32f2-42a1-b89f-203dfc0b6b98"}, {component: "text", label: "Last Name", initialValue: "2345432", type: "text", _uid: "6eff3638-80a7-4427-b07b-4c1be1c6b186"}]}, {component: "text", label: "Email", initialValue: "2345432", type: "email", _uid: "7f885969-f8ba-40b9-bf5d-0d57bc9c6a8d"}, {component: "text", label: "Phone", initialValue: "2345432", type: "text", _uid: "f61233e8-565e-43d0-9c14-7d7f220c6020"}]}, {component: "page", label: "Page 2", _uid: "3a30803f-135f-442c-ab6e-d44d7d7a5164", fields: [{component: "options", label: "Radio Buttons", type: "radio", initialValue: "2345432", _uid: "bd90f44a-d479-49ae-ad66-c2c475dca66b", options: [{component: "option", label: "Option 1", value: "one"}, {component: "option", label: "Option 2", value: "two"}]}, {component: "text", label: "Conditional Field", type: "text", _uid: "bd90f44a-d479-49ae-ad66-c2c475daa66b", initialValue: "2345432", conditional: {value: "two", field: "3a30803f-135f-442c-ab6e-d44d7d7a5164_bd90f44a-d479-49ae-ad66-c2c475dca66b"}}]}, {component: "page", label: "Page 3a", _uid: "cd392929-c62e-4cdb-b4dd-914035c1cc8d", initialValue: "2345432", conditional: {value: "one", field: "3a30803f-135f-442c-ab6e-d44d7d7a5164_bd90f44a-d479-49ae-ad66-c2c475dca66b"}, fields: [{component: "options", label: "More radio buttons", type: "radio", _uid: "a15bef56-ab67-4b98-a781-4441cc3bba56", initialValue: "2345432", options: [{component: "option", label: "Option 1", value: "one"}, {component: "option", label: "Option 2", value: "two"}]}]}, {component: "page", label: "Page 3b", _uid: "1dd4ec7c-fb53-47f4-af1b-1ab8f805b888", conditional: {value: "two", initialValue: "2345432", field: "3a30803f-135f-442c-ab6e-d44d7d7a5164_bd90f44a-d479-49ae-ad66-c2c475dca66b"}, fields: [{component: "options", label: "Something to toggle", type: "radio", _uid: "3ca9237d-e225-4950-a298-f81ce996cb85", options: [{component: "option", label: "Option 1", value: "one"}, {component: "option", label: "Option 2", value: "two"}]}, {component: "field_group", label: "Name", _uid: "b8406cb5-ff0d-4a83-a8f8-99740b6d91f7", fields: [{component: "text", label: "First Name", initialValue: "2345432", type: "text", _uid: "c6e065e1-dbcb-44ea-831f-ac3af889e964"}, {component: "text", label: "Last Name", initialValue: "2345432", type: "text", _uid: "e279ba9c-3c9b-4df8-b267-d14b3c2adcdd"}]}, {component: "text", label: "Email", initialValue: "2345432", type: "email", _uid: "a95208a0-7673-48a8-b704-2fb408fa6eec"}, {component: "text", label: "Phone", initialValue: "2345432", type: "text", _uid: "8dde5083-0619-42d6-8fc7-0563c35d03ad"}]}, {component: "page", label: "Page 4", _uid: "0c946643-5a83-4545-baea-065b27b51e8a", fields: [{component: "text", label: "Final Comment", initialValue: "2345432", type: "text", _uid: "f61231e8-565e-43d0-9c14-7d7f220c6020"}]}]
console .log (convert (formData))
.as-console-wrapper {max-height: 100% !important; top: 0}
The question also seems to imply that you want to do an update of the data. I would think of that as a separate step, which you already seem to be able to do.
The problem is in:
if (found) {
// console.log('entro', currentValue)
getInitialValues(currentValue?.fields)
return acc
}
this call to getInitialValues is supposed to return a result that is not saved into acc.
One way to correct it is to do something like this:
if (found) {
const res = getInitialValues(currentValue.fields);
return Object.assign(acc, res);
}
There may be other issues as well, but this is the one that stood up for me.
Note: two out of three of the uids in the "expected results" do not appear in the first code snippet (the example of formData).
As for the other one (with uid: 5b9b79d2-32f2-42a1-b89f-203dfc0b6b98) it has a label of 'First Name' not 'Conditional Field' - that's why it doesn't show up in the output.
(Full) Corrected code
function getInitialValues (formData = []) {
return formData.reduce((acc, currentValue) => {
const arrayOfStrings = ['page', 'field_group', 'options'];
const str = currentValue.component;
const found = arrayOfStrings.find((v) => str === v);
if (found) {
const res = getInitialValues(currentValue.fields);
return Object.assign(acc, res);
}
if (
(currentValue.component === 'text' || currentValue.component === 'select') &&
currentValue.label === 'Conditional Field'
) {
if (currentValue.initialValue) {
acc[currentValue._uid] = currentValue.initialValue;
}
}
return acc;
}, {});
I found a simple forEach loop with recursion to be easier.
const formData = [{
component: 'page',
label: 'Page 1',
_uid: '0c946643-5a83-4545-baea-055b27b51e8a',
fields: [{
component: 'field_group',
label: 'Name',
_uid: 'eb169f76-4cd9-4513-b673-87c5c7d27e02',
fields: [{
component: 'text',
label: 'First Name',
initialValue: '2345432',
type: 'text',
_uid: '5b9b79d2-32f2-42a1-b89f-203dfc0b6b98',
},
{
component: 'text',
label: 'Last Name',
initialValue: '2345432',
type: 'text',
_uid: '6eff3638-80a7-4427-b07b-4c1be1c6b186',
},
],
},
{
component: 'text',
label: 'Email',
initialValue: '2345432',
type: 'email',
_uid: '7f885969-f8ba-40b9-bf5d-0d57bc9c6a8d',
},
{
component: 'text',
label: 'Phone',
initialValue: '2345432',
type: 'text',
_uid: 'f61233e8-565e-43d0-9c14-7d7f220c6020',
},
],
},
{
component: 'page',
label: 'Page 2',
_uid: '3a30803f-135f-442c-ab6e-d44d7d7a5164',
fields: [{
component: 'options',
label: 'Radio Buttons',
type: 'radio',
initialValue: '2345432',
_uid: 'bd90f44a-d479-49ae-ad66-c2c475dca66b',
options: [{
component: 'option',
label: 'Option 1',
value: 'one',
},
{
component: 'option',
label: 'Option 2',
value: 'two',
},
],
},
{
component: 'text',
label: 'Conditional Field',
type: 'text',
_uid: 'bd90f44a-d479-49ae-ad66-c2c475daa66b',
initialValue: '2345432',
conditional: {
value: 'two',
field: '3a30803f-135f-442c-ab6e-d44d7d7a5164_bd90f44a-d479-49ae-ad66-c2c475dca66b',
},
},
],
},
{
component: 'page',
label: 'Page 3a',
_uid: 'cd392929-c62e-4cdb-b4dd-914035c1cc8d',
initialValue: '2345432',
conditional: {
value: 'one',
field: '3a30803f-135f-442c-ab6e-d44d7d7a5164_bd90f44a-d479-49ae-ad66-c2c475dca66b',
},
fields: [{
component: 'options',
label: 'More radio buttons',
type: 'radio',
_uid: 'a15bef56-ab67-4b98-a781-4441cc3bba56',
initialValue: '2345432',
options: [{
component: 'option',
label: 'Option 1',
value: 'one'
},
{
component: 'option',
label: 'Option 2',
value: 'two'
},
],
}, ],
},
{
component: 'page',
label: 'Page 3b',
_uid: '1dd4ec7c-fb53-47f4-af1b-1ab8f805b888',
conditional: {
value: 'two',
initialValue: '2345432',
field: '3a30803f-135f-442c-ab6e-d44d7d7a5164_bd90f44a-d479-49ae-ad66-c2c475dca66b',
},
fields: [{
component: 'options',
label: 'Something to toggle',
type: 'radio',
_uid: '3ca9237d-e225-4950-a298-f81ce996cb85',
options: [{
component: 'option',
label: 'Option 1',
value: 'one',
},
{
component: 'option',
label: 'Option 2',
value: 'two'
},
],
},
{
component: 'field_group',
label: 'Name',
_uid: 'b8406cb5-ff0d-4a83-a8f8-99740b6d91f7',
fields: [{
component: 'text',
label: 'First Name',
initialValue: '2345432',
type: 'text',
_uid: 'c6e065e1-dbcb-44ea-831f-ac3af889e964',
},
{
component: 'text',
label: 'Last Name',
initialValue: '2345432',
type: 'text',
_uid: 'e279ba9c-3c9b-4df8-b267-d14b3c2adcdd',
},
],
},
{
component: 'text',
label: 'Email',
initialValue: '2345432',
type: 'email',
_uid: 'a95208a0-7673-48a8-b704-2fb408fa6eec',
},
{
component: 'text',
label: 'Phone',
initialValue: '2345432',
type: 'text',
_uid: '8dde5083-0619-42d6-8fc7-0563c35d03ad',
},
],
},
{
component: 'page',
label: 'Page 4',
_uid: '0c946643-5a83-4545-baea-065b27b51e8a',
fields: [{
component: 'text',
label: 'Final Comment',
initialValue: '2345432',
type: 'text',
_uid: 'f61231e8-565e-43d0-9c14-7d7f220c6020',
}, ],
},
]
function getInitialValues(formData = [], output=[]) {
formData.forEach(obj => {
// first check for the Conditional Field label
let found = obj.hasOwnProperty('label') && obj.label === "Conditional Field";
// then loop through the component fields if neccesary
if (!found) ['select','text','options'].forEach(val => {
if (obj.hasOwnProperty('component') && obj.component === val) found = true;})
// if found update the output array
if (found) output.push({[obj._uid]: obj.initialValue})
// check for recursion
if (obj.hasOwnProperty('fields')) output = getInitialValues(obj.fields, output)
})
return output;
}
console.log(getInitialValues(formData))
trying to make this work....
I want to load nested data on two object model
Ext.application({
name : 'MyApp',
launch : function() {
Ext.define('MyApp.model.Address', {
extend: 'Ext.data.Model',
entityName: 'Address',
fields: [
{
name: 'id',
type: 'int'
},
{
name: 'addressLine',
type: 'string'
},
{
name: 'city',
type: 'string'
},
{
name: 'created',
type: 'date',
dateFormat: 'time',
persist: false
}
]
});
Ext.define('MyApp.model.User', {
extend: 'Ext.data.Model',
entityName: 'User',
fields: [
{
name: 'id',
type: 'int'
},
{
name: 'address',
reference: 'Address'
},
{
name: 'name',
type: 'string'
},
{
name: 'lastname',
type: 'string'
},
{
name: 'created',
type: 'date',
dateFormat: 'time',
persist: false
}
]
});
var user = new MyApp.model.User({
"id": 1,
"name": "Pedro",
"lastname": "Carbonell",
"address": {
"id": 1,
"addressLine": "Bailen 22",
"city": "Barcelona",
"created": 1420668866000
},
"created": 1420668866000
});
console.info(user);
console.info(user.getAddress());
}});
It's result on no error when created the user, but when I access to associated data via user.getAddress() it returned an exception:
Uncaught Error: The model ID configured in data ("[object Object]") has been rejected by the int field converter for the id fieldext-all-debug.js
Try to define proxy like memory or localstorage on model definitions, but the result it is the same.
Ext fiddle: https://fiddle.sencha.com/#fiddle/h2d
Any help will be appreciated!
Solved, but only find this solution: when use loadRawData...
var store = new Ext.data.Store({
model: MyApp.model.User
});
store.loadRawData({
"id": 1,
"name": "Pedro",
"lastname": "Carbonell",
"address": {
"id": 1,
"addressLine": "Bailen 22",
"city": "Barcelona",
"created": 1420668866000
},
"created": 1420668866000
});
console.info(store.first());
console.info(store.first().getAddress());
sample at this new fiddle: https://fiddle.sencha.com/#fiddle/h4e
you'r right, ext is a bit flaky, very....
I've been playing around with the code in your fiddle and not been able to get the association working the official way as of yet.
I simulated the functionality using this code:
Ext.define('MyApp.model.User', {
extend: 'Ext.data.Model',
fields: [{
name: 'id',
type: 'int'
}, {
name: 'name',
type: 'string'
}, {
name: 'lastname',
type: 'string'
}, {
name: 'created',
type: 'date',
dateFormat: 'time',
persist: false
}],
getAddress: function() {
if ('undefined' === this.data.address) {
return null;
}
return Ext.create('Address', this.data.address);
}
});
Basically I've removed the association and created a custom function to create a model record based off of the raw data passed in, You could also return a new, empty model if the address data does not exist instead of null, I used null as it's easier to determine whether you have a valid address record or not.
As already mentioned - this is not the official way to do this, I will have another play around with the fiddle and post a better solution once I find it, this may help in the meantime.
Using the original code, I made a few modifications and now it appears to be working.
Ext.application({
name : 'MyApp',
launch : function() {
Ext.define('MyApp.model.Address', {
extend: 'Ext.data.Model',
//entityName: 'Address',
fields: [
{
name: 'id',
type: 'int'
},
{
name: 'addressLine',
type: 'string'
},
{
name: 'city',
type: 'string'
},
{
name: 'created',
type: 'date',
dateFormat: 'time',
persist: false
}
],
hasMany: 'User'
});
Ext.define('MyApp.model.User', {
extend: 'Ext.data.Model',
//entityName: 'User',
fields: [
{
name: 'id',
type: 'int'
},
{
name: 'name',
type: 'string'
},
{
name: 'lastname',
type: 'string'
},
{
name: 'created',
type: 'date',
dateFormat: 'time',
persist: false
}
],
hasMany: { model: 'Address', name: 'Address' }
});
var user = new MyApp.model.User({
"id": 1,
"name": "Pedro",
"lastname": "Carbonell",
"address": {
"id": 1,
"addressLine": "Bailen 22",
"city": "Barcelona",
"created": 1420668866000
},
"created": 1420668866000
});
console.info(user);
console.info(user.data.address);
}
});
Is this the sort of thing you're after? I set Address manually on the User model. Not ideal but it's interpreted correctly as a record then.
Ext.define('MyApp.model.Address', {
extend: 'Ext.data.Model',
entityName: 'Address',
fields: [
{
name: 'id',
type: 'int'
},
{
name: 'addressLine',
type: 'string'
},
{
name: 'city',
type: 'string'
},
{
name: 'created',
type: 'date',
dateFormat: 'time',
persist: false
}
]
});
Ext.define('MyApp.model.User', {
extend: 'Ext.data.Model',
entityName: 'User',
fields: [
{
name: 'id',
type: 'int'
},
{
name: 'addressId',
reference: 'Address'
},
{
name: 'name',
type: 'string'
},
{
name: 'lastname',
type: 'string'
},
{
name: 'created',
type: 'date',
dateFormat: 'time',
persist: false
}
]
});
var user = new MyApp.model.User({
"id": 1,
"name": "Pedro",
"lastname": "Carbonell",
"created": 1420668866000
});
var addr = new MyApp.model.Address({
"id": 1,
"addressLine": "Bailen 22",
"city": "Barcelona",
"created": 1420668866000
});
user.setAddress(addr);
console.info(user);
console.info(user.getAddress());