CQ5 nested multi-field with select option - javascript

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..

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/

Overriding combo box for filtering items into the combobox, how to use this.filter item

I am using UI5 framework v1.38.39 and I want to do a custom combobox (no sap.m.Combobox but custom.comboboxsearch (which include sap.m.combobox and sap.m.comboboxbase)) where I can search what is inside (searching by contain) from key and text so I have something like follow in the custom control:
sap.ui.define([
"sap/m/ComboBox",
"sap/m/ComboBoxBase"
],
function (oComboBox, oComboBoxBase) {
"use strict";
/*some stuff*/
sValue = oEvent.target.value;
aVisibleItems1 = this.filterItems({
property: "text",
value: sValue
});
aVisibleItems2 = this.filterItems({
property: "key",
value: sValue
});
/*some stuff*/
My problem is that I don't have 2 filter, the second simply replace the first one then I don't have the items from the property text only from key, I would like to have both then I tried :
sValue = oEvent.target.value;
aVisibleItems1 = this.filterItems({
property: ["text","key"],
value: sValue
});
which give me the error :
Uncaught TypeError: p.charAt is not a function
at f.d.filterItems (ComboBox.js:6)
ComBox.js is a core file of UI5, then I tried :
sValue = oEvent.target.value;
aVisibleItems1 = this.filterItems({
property: "key" || "text",
value: sValue
});
Which also didn't work because take in consideration only key and no text, does someone has a solution ?
PS: As I use dynamic binding I suppose I cannot include items in view they are bind via another controller.
the view is :
<!--some stuff-->
<Label text="{i18n>MyText}" />
<Custom:ComboBoxSearch id="mycustombox" selectionChange='onChange'>
<core:Item key="{key}" text="{text}" />
</Custom:ComboBoxSearch>
<!--some stuff-->
items are added from the controller
mhm, i dont know if i understand your question right but i think it is this what you want.
<ComboBox
id="combobox1"
showSecondaryValues= "true"
items="{
path: '/yourdata',
sorter: { path: 'text' }
}">
<core:ListItem key="{key}" text="{text}" additionalText = "{key}"/>
</ComboBox>
and in your controller it should look like this:
this.getView().byId("combobox1").setFilterFunction(function(sTerm, oItem) {
return oItem.getText().match(new RegExp(sTerm, "i")) || oItem.getKey().match(new RegExp(sTerm, "i"));
});
so you can search for the key or the text it does not matter
sap.ui.ComboBox has a property called filterSecondaryValues which filters both the text and additionalText.
If you set 'additionalText' of the ListItem aggregation to the value of key (let showSecondaryValiues false if you dont wanna show them) and it should work?
<ComboBox
showSecondaryValues= "false"
filterSecondaryValues="true"
items="{
path: '/CountriesCollection'
}">
<core:ListItem key="{key}" text="{text}" additionalText="{key}"/>
</ComboBox>

Make single column editable in a UI5 smart table

I want to create a smart table with an editable column. I am using the metadata annotations to generate the table. The table property (editable = "true") makes all the columns editable. In my case, I want to make only a single column editable. I tried with the property sap:updatable="true" but it didn't work. Any ideas.
Thanks in advance.
This is my view by the way:
<mvc:View
xmlns="sap.m"
xmlns:mvc="sap.ui.core.mvc"
controllerName="QuickStartApplication3.controller.View1"
xmlns:smartFilterBar="sap.ui.comp.smartfilterbar"
xmlns:smartTable="sap.ui.comp.smarttable">
<smartFilterBar:SmartFilterBar
id="smartFilterBar"
entityType="Product">
<smartFilterBar:controlConfiguration>
<smartFilterBar:ControlConfiguration
key="ProductId"
visibleInAdvancedArea="true"
preventInitialDataFetchInValueHelpDialog="true" >
</smartFilterBar:ControlConfiguration>
</smartFilterBar:controlConfiguration>
<smartFilterBar:controlConfiguration>
<smartFilterBar:ControlConfiguration
key="Name"
visibleInAdvancedArea="true"
preventInitialDataFetchInValueHelpDialog="true" >
</smartFilterBar:ControlConfiguration>
</smartFilterBar:controlConfiguration>
<smartFilterBar:controlConfiguration>
<smartFilterBar:ControlConfiguration
key="Category"
visibleInAdvancedArea="true"
preventInitialDataFetchInValueHelpDialog="true" >
</smartFilterBar:ControlConfiguration>
</smartFilterBar:controlConfiguration>
</smartFilterBar:SmartFilterBar>
<smartTable:SmartTable
id="smartTable_ResponsiveTable"
smartFilterId="smartFilterBar"
tableType="ResponsiveTable"
editable="false"
entitySet="Products"
useVariantManagement="false"
useTablePersonalisation="true"
header="Products"
showRowCount="true"
useExportToExcel="true"
enableAutoBinding="true">
</smartTable:SmartTable>
</mvc:View>
I don't have enough rep to put a simple comment to your question but could you provide a sample of your view so that I can understand more precisely what you do?
Have you tried the use the sap.m.Table object as detailed here in the documentation :
https://sapui5.hana.ondemand.com/explored.html#/sample/sap.m.sample.TableEditable/preview
In order to have only certain cell editable you can manage it throught the template used see below how I changed the template in the onInit method of the controller:
onInit : function(evt) {
this.oModel = new JSONModel(jQuery.sap.getModulePath(
"sap.ui.demo.mock", "/products.json"));
this.oTable = this.getView().byId("idProductsTable");
this.getView().setModel(this.oModel);
this.oReadOnlyTemplate = this.getView().byId(
"idProductsTable").removeItem(0);
this.rebindTable(this.oReadOnlyTemplate, "Navigation");
this.oEditableTemplate = new sap.m.ColumnListItem({
cells : [ new sap.m.ObjectIdentifier({
title : "{Name}",
text : "{ProductId}"
}), new sap.m.Input({
value : "{Quantity}",
description : "{UoM}"
}), new sap.m.Input({
value : "{WeightMeasure}",
description : "{WeightUnit}"
}), new sap.m.Input({
value : "{Price}",
description : "{CurrencyCode}"
}) ]
});
If you don't use this object, then please tell me which one, I might be able to help.
Please have a look at the “Preview”-screenshot and the metadata.xml.
What happens if you set editable = "true" and annotate all properties of ‘Products’ with sap:updatable=”false”,
except for the single property that shall be editable, which you set to sap:updatable=”true”.
Don’t annotate entity set ‘Products’ with sap:updatable (or make sure that sap:updatable=”true”).

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>

Ext JS Search possibility in MultiSelect ComboBox

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.

Categories