Ext JS Search possibility in MultiSelect ComboBox - javascript

I want to know that how in ExtJS MultiSelect ComboBox i can search for a value. Like if i have entered 's' then a list of items starting with a must be displayed and the item selector should select if it matches with 's'.
This is the code i tried.....
cbCfg = {
name : property.columnname,
hideOnSelect : false,
triggerAction : 'all',
mode : 'local',
width : comboFieldSize,
store : new Ext.data.SimpleStore({
id : 0,
fields : ['strValue','strText'],
data : data
}),
listWidth : 400,
valueField : 'strValue',
displayField : 'strText'
};
field = new form.MultiCombo(cbCfg);
thnkz in advance,
just:-)

I assume that MultiSelect ComboBox extends functionality of Ext.form.ComboBox.
You could try going with triggerAction : 'query', which is the default - it should filter out non-matching entries. Although that could be a little bit counter-intuitive for the user.
Another possible approach is adding typeAhead : true property - should trigger suggesting suggestions based on the text entered by user.

Related

changing model property value is changing the same property in other object

im new to vue , i want user to be able to add some specific social media links to the page and edit some properties like it's text
i have 2 objects in my data , models and defaults
defaults contains selectable option for social media links and their initial values
basically i copy the default value into models and let the user customize the model via inputs
data () {
return {
models : [] ,
defaults : {
twitter : { id : null , placeholder : 'my twitter' , icon : 'twitter' , text : null , 'link' : null } ,
instagram : { id : null , placeholder : 'my instagram' , icon : 'instagram' , text : null , 'link' : null } ,
tiktok : { id : null , placeholder : 'my tiktok' , icon : 'tiktok' , text : null , 'link' : null } ,
} ,
}
} ,
so there a select menu for user to select which social he wants to add to the page
Select :
<ul >
<li v-for="(social, index ) in defaults" :key="index">
<a #click="appendSocial(index)">
{{ index }}
</a>
</li>
</ul>
here is my #click="appendSocial(index)" function
appendSocial(type){
let typedefault = this.defaults[type];
this.models.push(typedefault)
},
and finally i show my models to user and provide an input for editing it's text via v-model
<div v-for="(model, index) in models" v-bind:key="model.id">
<a class="button-preview">
{{ model.text === null ? model.placeholder : model.text }}
</a>
<label>Text</label>
<input type="text" v-model="model.text" :key="index" :placeholder="model.placeholder">
</div>
so here is the problem , for some reason changing the models properties will change the same property in defaults ... and changing defaults properties will change the same property models !!
like if i add a twitter menu to the page and change it's text (model.text) to abc via v-model ... it will also change defaults.twitter.text to abc
to better demonstrate the problem i've added some console log to my appendSocialfunction
appendSocial(type){
let typedefault = this.defaults[type];
console.log(`-------- default object for ${type} -----------`);
console.log(typedefault);
this.addElement(typedefault);
},
here is the result
1 - i've selected a twitter link and added to my models , you can see defaults.twitter.text is null
2 - i've change my model.text (i suppose it would be models[0].text) to abc
3 - i've added another twitter link to my page ... this time defaults.twitter.text is also abc
also changing defaults properties will effect all the models the has been getting their value from that default object
like if i change the defaults.instagram.text to xyz all my models which have got their initial values from defaults.instagram will also change their text to xyz
it's like they are referencing each other , but i haven't passed the value between 2 objects by reference
im not sure what's happening here and how can i prevent this ?
This is because
let typedefault = this.defaults[type];
this.models.push(typedefault)
Is storing the reference to the object into your this.models array. And so if you mutate the element, you're by default changing the base object. A quick and dirty way of doing a deep clone is the following.
let typedefault = this.defaults[type];
let clonedObj = JSON.parse(JSON.stringify(typedefault));
this.models.push(clonedObj)
Note: Lodash library does have a proper deep clone functionality.
https://www.geeksforgeeks.org/lodash-_-clonedeep-method/

How to display list of pages related to a tag in xwiki

I use xwiki to create a wiki. I want to dynamicaly display a list of pages (in a livetable or just bulk.), so I use the tag system.
Currently I use the HTML macro + iframe but it display all the page with header, side menus, options, etc.
I've tried this snippet but nothing is displaying and I don't really understand all the code, I'm not sure that is the good solution.
I've tried to use Display and Include macros :
{{display reference="Main.Tags"/}}
It display all my tags in a cloud.
But to had what I want I should specify this code with
queryString="do=viewTag&tag=Test"
Or something like that but I don't know how to do it.
So if you have an idea to display the list of pages with the same tag I will be happy to read it :)
Thanks.
EDIT1
So I work on it and I display what i want with the following instruction :
{{velocity}}
#set ($list = $xwiki.tag.getDocumentsWithTag('test'))
#foreach($doc in $list)
$doc
#end
{{/velocity}}
But the problem is that display all the path of the document.
Wiki Interne.2\. Liste des flux TEST.2_1_Flux_Externes_Entrants.AGDAT01.WebHome
Wiki Interne.2\. Liste des flux TEST.2_1_Flux_Externes_Entrants.AGOL20.WebHome
Wiki Interne.2\. Liste des flux TEST.2_1_Flux_Externes_Entrants.AGOL21.WebHome
Wiki Interne.2\. Liste des flux TEST.2_1_Flux_Externes_Entrants.AGOL22.WebHome
How can I restrict the display only to the title of the document?
You can use the Livetable macro (http://extensions.xwiki.org/xwiki/bin/view/Extension/Livetable%20Macro) to list the pages you want and customize it to only show the pages tagged with a specific tag.
{{velocity}}
#set($collist = ['doc.title', 'doc.location', 'doc.date', 'doc.author'])
#set($colprops = {
'doc.title' : { 'size' : 30, 'link' : 'view', 'filterable': false, 'sortable': false },
'doc.location' : { 'html' : true },
'doc.date' : { 'type' : 'date' },
'doc.author' : { 'type' : 'text', 'link' : 'author' }
})
#set($options = {
'translationPrefix' : 'platform.index.',
'rowCount' : 15,
'tagCloud' : 'true',
'selectedTags' : ['test']
})
#if(!$isGuest)
#set($discard = $collist.add('_actions'))
#set($discard = $colprops.put('_actions', { 'actions' : ['copy', 'delete', 'rename', 'rights'] }))
#end
#livetable('taggedDocs' $collist $colprops $options)
{{/velocity}}
Since the 'tagCloud' option needs to be enabled in order for the 'selectedTags' option to allow you to list the tags you want to show by default (in my example, I am listing pages tagged with the tag 'test'), you will also see all the other available tags that the user could select from. If that bothers you and you want to not allow the user to change the displayed tag, you could simply hide the 'tagCloud' section above the livetable by going in object edit mode on the page and adding an object of type 'StyleSheetExtension' (see http://www.xwiki.org/xwiki/bin/view/Documentation/DevGuide/Tutorials/SkinExtensionsTutorial/#HMinimalStyleSheeteXtension for more details) with the following CSS content:
#alldocs-tagcloud {
display : none;
}
Thanks #Eduard Moraru :) I will try it.
However I've resolved my case when I found the Velocity doc : http://velocity.apache.org/engine/1.7/user-guide.html
The code for people who might be interested :
{{velocity}}
#set ($list = $xwiki.tag.getDocumentsWithTag('Your Tag'))
#foreach($reference in $list)
#set ($document = $xwiki.getDocument($reference))
#set ($label = $document.getTitle())
[[$label>>$reference]]
#end
{{/velocity}}
Try this, it is shameless cut fron build-in tag app.
{{velocity}}
#set ($tag='Tag')
#if ("$!{request.get('renamedTag')}" != '')
{{info}}$services.localization.render('xe.tag.rename.success', ["//${request.get('renamedTag')}//"]){{/info}}
#end
#set ($list = $xwiki.tag.getDocumentsWithTag($tag))
{{container layoutStyle="columns"}}
(((
(% class="xapp" %)
=== $services.localization.render('xe.tag.alldocs', ["//${tag}//"]) ===
#if ($list.size()> 0)
{{html}}#displayDocumentList($list false $blacklistedSpaces){{/html}}
#else
(% class='noitems' %)$services.localization.render('xe.tag.notags')
#end
)))
{{/container}}
#set ($displayDocExtra = false)
{{/velocity}}

CQ5 nested multi-field with select option

I will need to add the values that editor writes them in textfield from dialog panel into a <select> option. I have created the multi-field option for the dialog component, but not sure how I should get values in the <select> it self.
I'm using the JS widget for multi-field, you can find it here. I know that the multi-field JS should return a JSON array of options, how do I achieve this in my case?
Here's my XML markup:
<developer
jcr:primaryType="cq:Widget"
title="Data"
xtype="panel">
<items jcr:primaryType="cq:WidgetCollection">
<developer
jcr:primaryType="cq:Widget"
fieldDescription="Click the '+' to add a new data"
fieldLabel="Dev Data"
name="./devdata"
xtype="multifield">
<fieldConfig
jcr:primaryType="cq:Widget"
xtype="devprofile"/>
</developer>
</items>
</developer>
JavaScript that is adding the textfield for multi-field
this.developerName = new CQ.Ext.form.TextField({
fieldLabel : "Developer's Name",
allowBlank: true,
width : 400,
listeners : {
change : {
scope : this,
fn : this.updateHidden
},
dialogclose : {
scope : this,
fn : this.updateHidden
}
}
});
this.add(this.developerName);
And the markup:
<c:if test="${not(empty(developerName))}">
<select id="use-names" class="js-example-basic-multiple">
<option>Example</option>
<option>${developerName}</option>
</select>
</c:if>
Please let me know if you need more detailed shared.
ACS commons has pretty good working example of custom multifield. Take a look at https://adobe-consulting-services.github.io/acs-aem-commons/features/widgets.html
Just replace textarea with your dropdown and you will have what you need..

Replicate data into JQGrid

I am creating a jqgrid i m creating a row with 2 columns with dropdown box. The dropdowns are getting populated using ajax call. My requirement is I want to replicate this row on click on ADD button in UI. For example for now one row is coming into jqgrid, after clicking ADD button a new row with same content with out refreshing the changed value in first row should be displayed. Is there any way to do that? My jqgrid code is
$("#tbl").jqGrid('GridUnload');
$("#tbl").jqGrid(
{
url : "/searchCriteria.do",
datatype : 'json',
colModel :
[
{name : "test1",label : "TEST1", search : false,cellEdit:true, editable: true,edittype:"select",width:150 ,formatter: createDropDown,title:false},
{name : "test2",label : "TEST2", search : false,cellEdit:true, editable: true,edittype:"select",width:150 ,formatter: createDropDown,title:false}
],
viewrecords: true,
loadonce:true,
width: 1000,
multiselect : true
});
});
You can use a combination of the getLocalRow and addRowData methods to achieve your functionality. Docs for these methods.
Let's say in your HTML you have a button:
<button id="add" type="button">ADD</button>
In your javascript you could have:
<script>
$("#add").click(function(){
var id_of_new_row = something; //you haven't specified which are the exact rows you'd like selected.
//you could use the getDataIDs method to get the row-IDs you're looking for
var new_row_data = $("#gridId").jqGrid('getLocalRow', id_of_new_row));
$("#gridId").jqGrid('addRowData',id_of_new_row+1, new_row_data, "last");
});
</script>

SetRowData and DirtyCells

I'm using SetRowData to set some row data in a jqGrid
jqColModel = gJqGrid.jqGrid('getGridParam','colModel');
rowData = gJqGrid.jqGrid('getRowData', rowid);
for (var i=0; i<newData.length; i++){
rowData[jqColModel[i+1].name] = newData[i];
}
gJqGrid.jqGrid('setRowData', rowid, rowData);
This is working as expected. The jqGrid row is being updated with the values from the newData object.
I'm then trying to get all the modified cells using
jqRows = gJqGrid.jqGrid('getChangedCells', 'dirty');
but this doesn't seem to be working. I'm trying to batch up all the changes and create a custom save event
My grid definition is as below
$(gJqSel_Table).jqGrid({
caption : 'jqGrid'
, datatype : 'local'
, loadonce : true
, data : formattedLineData
, colNames : customColNames
, colModel : customColModel
, autoencode : true
, rowNum : 1000
, keys : true
, sortable : false
, hidegrid : false
, multiselect : false
, altRows : false
, height : '100%'
, autowidth : true
, shrinkToFit : true
, cellEdit : gSettings.editMode
, cellsubmit : 'clientArray'
, afterEditCell : function (rowid) {
var $editControl = $("#" + rowid).find("input, select, textarea");
if ($editControl){
$editControl.on('paste', function(e) {
GridPaste(e, rowid);
});
}
}
});
Can someone provide some guidance about how I can
use a JSON object to set all the cell values of a row
flag each cell in the row as dirty so that the getChangedCells method knows that the values have changed?
After more reading of the jqGrid documentation I found this
setRowData
Do not use this method when you are editing the row or cell. This will
set the content and overwrite the input elements.
http://www.trirand.com/jqgridwiki/doku.php?id=wiki:methods
Changing my code to use the setCell method works
Cell value is updated
Cell is marked as dirty and included in the getChangedCells results
My code is as below
jqColModel = gJqGrid.jqGrid('getGridParam','colModel');
for (var i=0; i<newData.length; i++){
colName = jqColModel[i].name;
gJqGrid.jqGrid('setCell', rowid, colName, newData[i], 'dirty-cell');
}
Updated
As #Oleg pointed out in the comments, I also had to add the following to mark the jqGrid line as edited:
gJqGrid.setRowData(rowid, false, 'edited');

Categories