Selectize customize options view - selectize.js

I try to customize multiple select (with selectize.js plugin)
I have the payload with next structure:
[
{id: 1, name: 'First', email: 'first#ok.ob'},
{id: 2, name: 'Second', email: 'second#ok.ob'},
.....
]
how I can customize option to see text in next format
First <first#ok.ob>
Second <second#ok.ob>
but when person is selected in input field it should be displayed like
First Second
without additional parameters
Maybe someone can provide link to documentation or solution, because I couldn't find any information about this case.
Thx.

Selectize has a render callback function for Custom rendering.
You can take a look here
You can mention it in its config object. I have used it something like below -
config = {
valueField: 'id',
labelField: 'firstName',
searchField: ['id', 'firstName', 'lastName', 'userName', 'cell'],
maxItems: 1,
render: {
item: (item: any, escape: any) => {
return `<div>` +
escape(item.firstName) + ` ` + escape(item.lastName) +
` <span><` + escape(item.userName) + `></span>` +
`</div>`;
},
option: (item: any, escape: any) => {
return this.templateCustomer(item, escape);
}
},
};

Related

Querying a sub document of a sub document in mongoose

Inside my parent I have many childs and in one of them childs they also have many sub childs, I need to return the sub childs from a specific child.
exports.test = (req, res) => {
Forum.find({title: req.params.id}).then(record => {
console.log(record);
})
};
The code here returns the following when I insert the News & Announcement url param which is correct:
_id: 5e7bf52ebb5b2b09fb46e29f,
title: 'News & Announcements',
property: 'ACP',
position: 1,
visible: true,
topics: [ [Object], [Object], [Object] ],
__v: 5 } ]
I then want to access the topics and return a specific topic - finding it by a name/title as I did above, how would I do this?
If this topics field is an array of objects and each object contains the name and title, then you can search for the topic you want, just add that to the object you passed to the find query
for example, If you need to query for some topic with name 'My Topic', then the query should be
Forum.find({ title: req.params.id, 'topics.name': 'My Topic' })
this will narrow down the results of the query but if there are some other topics with different names in the same forum, they will be come with you in the query
for example, if some forum has the following info:
{
_id: ObjectId("5e7bf52ebb5b2b09fb46e29f"),
title: 'News & Announcements',
property: 'ACP',
position: 1,
visible: true,
topics: [
{
name: 'Topic 1',
title: 'Title 1'
}, {
name: 'Topic 2',
title: 'Title 2'
}, {
name: 'My Topic',
title: 'My Title'
}
],
}
and you search for the topic 'My Topic' only in this forum, all the topics array will be returned from the query, as the search is done per documents
so you have to do some javaScript trick after finishing the query to get only the topic that has the name you wanted
var myTopic = record.ropics.filter(topic => topic.name === 'My Topic'}
this will return the topic you wanted only

Creating forms in Aposstrophe CMS

I am following this tutorial to create a form in my project, which is leveraging the Apostrophe CMS. When i follow the tutorial, I am able to create the form and submit, and understand how to view the form submission in the Admin Console.
However, when I begin to customize the form to fit my project-specific needs, I break the form, causing the form validation to fail. The error i get upon submitting the form is:
TypeError: Cannot read property 'length' of undefined
at Object.convertString [as convert] (user.js:727)
at user.js:145
at async.js:181
at iterate (async.js:262)
at Object.async.forEachOfSeries.async.eachOfSeries (async.js:281)
at Object.async.forEachSeries.async.eachSeries (async.js:214)
at Object.self.convert (user.js:127)
at convert (always.js:57)
at async.js:718
at iterate (async.js:262)
My changes, other then adjusting the field definition object of my contact-form:index.js file, are mostly in the contact-form-widgets:widget.html file.
In the tutorial, the contact-form-widgets:widget.html view imports apostrophe-schemas:macros.html, and uses html files from the apostrophe-schemas and apostrophe-ui modules to build the html of the form. My specific questions therefore have to do with the importance of those two modules. Are those modules simply used for the front end display of the form? Do the contents of the views of those modules have any bearing on the submission and post-submissions tasks of the form? If the answer is negative, this means I am not configuring the form correctly, so therefore, are there any resources to help solve that problem?
Here is my contact-form:index.js config file:
var async = require('async');
module.exports = {
extend: 'apostrophe-pieces',
name: 'contact-form',
label: 'Contact Form',
alias: 'contactForm',
addFields: [
{
name: 'name',
type: 'string',
label: 'First & Last Name',
required: true
},
{
name: 'company',
type: 'string',
label: 'Company Name',
required: true
},
{
name: 'email',
type: 'string',
label: 'Email Address',
required: true
},
{
name: 'phone',
type: 'string',
label: 'Phone Number & Extension',
required: true
},
{
name: 'subject',
type: 'string',
label: 'Subject',
required: true
},
{
name: 'message',
type: 'string',
label: 'Message',
textarea: true,
placeholder: "Don't be stupid"
}
],
permissionsFields: false,
afterConstruct: function(self) {
self.setSubmitSchema();
},
construct: function(self, options) {
self.setSubmitSchema = function() {
self.submitSchema = self.apos.schemas.subset(self.schema,
[ 'name', 'company', 'email', 'phone', 'subject', 'message' ]
);
};
self.submit = function(req, callback) {
var piece = {};
return async.series([
convert,
insert
], callback);
function convert(callback) {
return self.apos.schemas.convert(req, self.schema, 'form', req.body, piece, callback);
}
function insert(callback) {
return self.insert(req, piece, { permissions: false }, callback);
}
};
}
};
I'm the lead developer of Apostrophe at P'unk Avenue. We had some conversation in another forum but just for the record, there turned out to be two issues:
The form was submitting on any button click because that is what button elements do when they are of type "submit," and "submit" is the default value for type (at least in some browsers). It's not an Apostrophe issue and can be resolved by setting the type attribute as desired.
The form markup was custom and did not have wrapper elements such as data-name="title", etc. (corresponding to the schema) around the actual form field elements. You may use custom markup but all of the "moving parts" found in our official schemaMacros.html need to be there, i.e. the data attributes need to exist.
We do plan to make it easier to use custom markup without those wrappers, at least in cases where we can figure out which fields are which without them.
FYI, an element of type="file" will not work out of the box, but check out the attachment field type in apostrophe's schemas, which is pretty amazing for that role.

Multiselect search whole string

I have a multiselect with search bound to a store (with attribute string_value). Search only searches strings that start with "string to search" instead of contains "string to search" (similar to searching for '%string%' instead of 'string%'). Is there a way to do this by extending 'multiselector-search'?
Below is my multiselector control bound to a form:
var ms = Ext.widget('form', {
xtype: 'multi-selector',
width: 400,
height: 300,
requires: [
'Ext.view.MultiSelector'
],
layout: 'fit',
renderTo: Ext.getBody(),
items: [{
bbar: [{
xtype: 'button',
itemId: 'button',
html: 'Toolbar here',
text: 'Submit request to API',
// get submitted array
handler: function() {
if (cardioCatalogQT.config.mode === 'test') {
console.log('In submitted values handler: ');
}
var submitted = Ext.getCmp('test');
var dx = [];
Ext.Array.each(submitted.store.data.items, function (item) {
dx.push(item.data.string_value);
}); // each()
Ext.Msg.alert('Submitted Values',
'The following diagnoses will be sent to the server: <br
/>' + dx);
if (cardioCatalogQT.config.mode === 'test') {
console.log(dx);
}
}
}],
xtype: 'multiselector',
title: 'Selected Dx',
id: 'test',
name:'test',
fieldName: 'string_value',
viewConfig: {
deferEmptyText: false,
emptyText: 'No Dx selected'
},
// TODO: fix ability to remove selected items when box is unchecked
search: {
field: 'string_value',
store: 'Diagnoses'
}
}]
}).center();
The closest I could find to this problem was http://www.sencha.com/forum/showthread.php?240887. I tried making it work with the multiselect search with no success.
The MultiSelector uses the Ext.util.Filter to narrow the results based on the typed text. You need to enable the anyMatch property for it to match anywhere.
To do that, you'll have to include a new "search" function in your multiselector's search object that will have anyMatch=true.
Please see my fiddle, https://fiddle.sencha.com/#fiddle/jf5, for an example of how to do this.

Coffeescript / Node.js - How to remove elements from an object based on comparison with DB

I'm working on a project which will post periodic XML updates for users. I'm attempting to suppress information which hasn't changed since the last update.
Within node.js, I have assembled a user object which will be used to generate the XML:
users =
# actual application has 25 properties per user
[
{
USERID: 150927,
EMAIL: 'irving.block#email.net',
FIRSTNAME: 'Irving',
LASTNAME: 'Block',
COLOR: 'Green'
},
{
USERID: 1246007,
EMAIL: 'allen.adler#email.net',
FIRSTNAME: 'Adler',
LASTNAME: 'Allen',
COLOR: 'Blue'
},
{
CLKEY: 1248350,
EMAIL: 'walter.pidgeon#email.net',
FIRSTNAME: 'Walter',
LASTNAME: 'Pidgeon',
COLOR: 'Red'
}
]
I also have an object loaded which helps map user data to the eventual XML fields:
xml_map =
[
{
ID: 1,
ELEMENT: 'xml_map_assigned_id',
MAPPPED: 'USERID'
},
{
ID: 2,
ELEMENT: 'xml_map_email_address',
MAPPPED: 'EMAIL'
},
{
ID: 3,
ELEMENT: 'xml_map_user_firstname',
MAPPPED: 'FIRSTNAME'
},
{
ID: 4,
ELEMENT: 'xml_map_user_lastname',
MAPPPED: 'LASTNAME'
},
{
ID: 5,
ELEMENT: 'xml_map_user_color',
MAPPED: 'COLOR'
}
]
Using these objects, I need to compare with the last update, and remove matching properties (since I only want to post updates for data that has changed). Here's an example of what the last update (stored in the DB) might look like:
# nothing like this is used in the real application
# just showing here to give an idea of what the DB could look like
db_data =
[
{
USERID: 150927,
EMAIL: 'irving.block#email.net',
FIRSTNAME: 'IRVING',
LASTNAME: 'Block',
COLOR: 'Orange'
},
{
USERID: 1246007,
EMAIL: 'new.email#somewhere.com',
FIRSTNAME: 'Adler',
LASTNAME: 'Allen',
COLOR: 'Blue'
},
{
USERID: 1248350,
EMAIL: 'walter.pidgeon#email.net',
FIRSTNAME: 'Walt',
LASTNAME: 'Pidgeon',
COLOR: 'Red'
}
]
Using these examples, I'd like to end up with a User object like this (since only 1 thing has changed for each user):
users_final =
[
{
USERID: 150927,
COLOR: 'Orange'
},
{
USERID: 1246007,
EMAIL: 'new.email#somewhere.com',
},
{
USERID: 1248350,
FIRSTNAME: 'Walt',
}
]
And now for the pseudo-code that shows how I've been trying to accomplish this:
async = require "async"
handleChanges = (users, map, callback) ->
sql1 = "select..."
sql2 = "update..."
sql3 = "insert..."
db.query sql1, [], (err, rows, def) ->
if err? then console.log err
if rows[0]
if rows[0].ELEMENT_VALUE.toString() is users[map.MAPPED].toString()
# nothing has changed since last update
db.query sql2, ['Old'], (err, rows, def) ->
if err? then console.log err
callback null, map.MAPPED
else # this value has changed since the last update. Run update query
db.query sql2, ['New'], (err, rows, def) ->
if err? then console.log err
callback null, null
else # no value has ever been saved for this combo. Run insert query
db.query sql3, [], (err, rows, def) ->
if err? then console.log err
callback null, null
updateStore = (users, callback) ->
for map in xml_map
do(map) ->
handleChanges users, map, (err, del) ->
if del? then delete r[del]
callback null, r
async.map users, updateStore, (err, results) ->
console.log results
This obviously doesn't work right. I'm sure the updateStore function needs to be doing something different, but I'm at a loss.
Thanks in advance for your help!
I did similar thing in the project, but I use json instead of xml.
What I have done is
retrieve a list of objects from db. and calculate a hash value for each of the object.
users =
[
{
USERID: 150927,
EMAIL: 'irving.block#email.net',
FIRSTNAME: 'Irving',
LASTNAME: 'Block',
COLOR: 'Green'
},
{
USERID: 1246007,
EMAIL: 'allen.adler#email.net',
FIRSTNAME: 'Adler',
LASTNAME: 'Allen',
COLOR: 'Blue'
}
]
hash = [
'c8addc875913a367486ba8343f68e349667e0334',
'df3d067e876437996237d0fde90466703ea303b9'
]
on the client side, I do compare the each old hash to the new hash. if different I use php.js or underscore.js. php.js can do array_diff to get differents between two object. Of course you can just do array_diff with comparing hash.
If your data structure is nested like this
{
User: {
FIRSTNAME: 'Irving',
LASTNAME: 'Block',
USERID: 150927
}
OtherInfo: {
EMAIL: 'irving.block#email.net'
}
}
you can flatten it to following before doing array_diff because array_diff only work on one level.
{
"User.FIRSTNAME": 'Irving',
"User.LASTNAME": 'Block',
"User.USERID": 150927,
"OtherInfo.EMAIL": 'irving.block#email.net'
}
I'm not sure if there is enough information about your expected XML output for me to help there, but the users_final result you are looking for can be calculated with a fairly straight forward comparison algorithm. The core algorithm is:
difference = (a, b, idFieldName) ->
if a[idFieldName] != b[idFieldName]
throw new Error("#{idFieldName} values must match.")
diff = {}
diff[idFieldName] = a[idFieldName]
isDifferent = false
for key, value of b
if key != idFieldName and a[key].toUpperCase() != value.toUpperCase()
isDifferent = true
diff[key] = value
if isDifferent
return diff
else
return false
Here is a fully working example including using the input you provided... with one exception. I think you have a typo in your users literal. I switched it from CLKEY to USERID so it matches the other rows. Just click on the "Run" button in the upper right hand corner after following the link to see your expected users_final result.

Grid store config throws "Uncaught TypeError: Cannot read property 'buffered' of undefined"

I have form and grid. the user must enter data in form fields then display related records in the grid.
I want to implement a search form, e.g: user will type the name and gender of the student,
then will get a grid of all students have the same name and gender.
So, I use Ajax to send form fields value to PHP and then create a json_encode which will be used in grid store.
I am really not sure if my idea is good. But I haven't found another way to do that.
The problem is there is a mistake in my store but I couldn't figure out what it is. I get this error:
Uncaught TypeError: Cannot read property 'buffered' of undefined
My View:
{
xtype: 'panel',
layout: "fit",
id: 'searchResult',
flex: 7,
title: '<div style="text-align:center;"/>SearchResultGrid</div>',
items: [{
xtype: 'gridpanel',
store: 'advSearchStore',
id: 'AdvSearch-grid',
columns: [{
xtype: 'gridcolumn',
dataIndex: 'name',
align: 'right',
text: 'name'
}, {
xtype: 'gridcolumn',
dataIndex: 'gender',
align: 'right',
text: 'gender'
}
],
viewConfig: {
id: 'Arr',
emptyText: 'noResult'
},
requires: ['MyApp.PrintSave_toolbar'],
dockedItems: [{
xtype: 'PrintSave_tb',
dock: 'bottom',
}]
}]
}
My Controller:
.
.
.
xmlhttp.open("GET","AdvSearch.php?search_name="+search_name,true);
xmlhttp.send(null);
My PHP script:
if (!$con) {
throw new Exception("Error in connection to DB");
}
$query ="SELECT name, gender FROM students WHERE name ILIKE '%$search_name%' ";
$result = pg_query($query);
while ($row = pg_fetch_array($result)) {
$Arr[] = array('name' => $row[0], 'gender' => $row[1]);
}
$searchResult_list = array();
$searchResult_list['success'] = true;
$searchResult_list['Arr'] = $Arr;
$searchResult_list['totalCount'] = count( $searchResult_list['Arr'] );
echo json_encode($searchResult_list);
if (!$result)
die("Error in query: " . pg_last_error());
pg_close($con);
My Store, Model:
Ext.define('AdvSearchPost', {
extend: 'Ext.data.Model',
proxy: {
type: 'ajax',
url: 'AdvSearch.php',
reader: {
type: 'json',
root: 'Arr',
totalProperty: 'totalCount'
}
},
fields: [{
name: 'name'
}, {
name: 'type_and_cargo'
}
]
});
advSearchStore = Ext.create('Ext.data.Store', {
pageSize: 10,
model: 'AdvSearchPost'
});
Well it is just a typo of your storename.
The error Uncaught TypeError: Cannot read property 'buffered' of undefinedonly indicates that the store could not be bound. It may be a bit misleading.
Try the grid with either
store: advSearchPost
or
store: Ext.StoreMgr.lookup('AdvSearchPost') // if in any form a controller takes care about your store
and it will work.
Edit
I guess you haven't any controller so I recommend you to create your store like this
Ext.create('Ext.data.Store', {
pageSize: 10,
model: 'AdvSearchPost',
storeId: 'AdvSearchPost'
});
That will enable you to receive the store by the StoreManager from everywhere (after it is created). That will also enable the last statement to work without any controller.
Even if you call like this..
store: Ext.StoreMgr.lookup('bla bla bla') won't throw any error in the console.
Replace store parameter with storeId and then assign your actual store to it which will connect to your actual store. storeId:advSearchPost

Resources