I am creating a multifield component having 2 textfields. Following is my dialog xml.
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
jcr:primaryType="cq:Dialog"
title="dialog"
xtype="dialog">
<items jcr:primaryType="cq:WidgetCollection">
<links
jcr:primaryType="cq:Widget"
fieldLabel="QuickLinks"
name="./links"
xtype="multifield">
<fieldConfig
jcr:primaryType="cq:Widget"
xtype="multifield">
<items jcr:primaryType="cq:WidgetCollection">
<title
jcr:primaryType="cq:Widget"
fieldLabel="Title"
hideLabel="{Boolean}false"
name="./jcr:title"
xtype="textfield"/>
<url
jcr:primaryType="cq:Widget"
fieldLabel="URL"
name="./jcr:url"
xtype="textfield"/>
</items>
</fieldConfig>
</links>
</items>
</jcr:root>
I am able to edit the content, and the content gets saved. However I have 2 problems - 1) When the dialog loads, it is empty always, and it doesnt show the saved content when I reopen the dialog 2) The up and down arrows are not working any more. Any suggestions to fix these is highly appreciated. Thank you very much.
The multifield xtype's field config takes only one item (i.e you can have one textfield in it. When multiple values are configured they will be stored as a multivalued property called links and when only one value is configured it'll be stored as a single valued property called links). The entire data configured in your multifield will be stored as links property in your node. You won't be able to get them as "jcr:title" and "jcr:url".
You should create a custom xtype say "linksXtype" that stores the "jcr:title" and "jcr:url" as a single string separated by some pattern say "***" ("jcr:title***jcr:url").
You can find the details of creating a custom xtype here : link
The xtype can be created like this:
Ejst.CustomWidget = CQ.Ext.extend(CQ.form.CompositeField, {
/**
* @private
* @type CQ.Ext.form.TextField
*/
hiddenField: null,
/**
* @private
* @type CQ.Ext.form.ComboBox
*/
jcrtitle: null,
/**
* @private
* @type CQ.Ext.form.TextField
*/
jcrurl: null,
constructor: function(config) {
config = config || { };
var defaults = {
"border": false,
"layout": "table",
"columns":2
};
config = CQ.Util.applyDefaults(config, defaults);
Ejst.CustomWidget.superclass.constructor.call(this, config);
},
// overriding CQ.Ext.Component#initComponent
initComponent: function() {
Ejst.CustomWidget.superclass.initComponent.call(this);
this.hiddenField = new CQ.Ext.form.Hidden({
name: this.name
});
this.add(this.hiddenField);
this.jcrtitle = new CQ.Ext.form.TextField({
fieldLabel:"Jcr url",
cls:"ejst-customwidget-1",
listeners: {
change: {
scope:this,
fn:this.updateHidden
}
},
optionsProvider: this.optionsProvider
});
this.add(this.jcrtitle);
this.jcrurl = new CQ.Ext.form.TextField({
fieldLabel:"Jcr Title",
cls:"ejst-customwidget-2",
listeners: {
change: {
scope:this,
fn:this.updateHidden
}
}
});
this.add(this.jcrurl);
},
// overriding CQ.form.CompositeField#setValue
setValue: function(value) {
var parts = value.split("/");
this.jcrtitle.setValue(parts[0]);
this.jcrurl.setValue(parts[1]);
this.hiddenField.setValue(value);
},
// overriding CQ.form.CompositeField#getValue
getValue: function() {
return this.getRawValue();
},
// overriding CQ.form.CompositeField#getRawValue
getRawValue: function() {
return this.jcrtitle.getValue() + "***" +
this.jcrurl.getValue();
},
// private
updateHidden: function() {
this.hiddenField.setValue(this.getValue());
}
});
// register xtype
CQ.Ext.reg('linksXtype', Ejst.CustomWidget);
change the dialog.xml to something like this
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:cq="http://www.day.com/jcr/cq/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0"
jcr:primaryType="cq:Dialog"
title="dialog"
xtype="dialog">
<items jcr:primaryType="cq:WidgetCollection">
<links
jcr:primaryType="cq:Widget"
fieldLabel="QuickLinks"
name="./links"
xtype="multifield">
<fieldConfig
jcr:primaryType="cq:Widget"
xtype="linksXtype">
</fieldConfig>
</links>
</items>
</jcr:root>
To fetch the values iterate over the string array stored as links property and split each string by "***"
EDIT :
Adobe consultancy services under its ACS-Commons package provides a more elegant multifieldpanel widget to handle this use case. It simplifies the approach and eliminates the need to write a custom xtype for every combination of required fields. The data is stored in form of JSON format and comes with taglibs to extract data from the node. Link : http://adobe-consulting-services.github.io/acs-aem-commons/features/widgets.html#multi-field-panel-since-150
As Sharath says, you'll need to define your own custom XType, rather than putting multiple fields in the multifield itself.
As an alternative to concatenating fields within a String[]
property, another approach is to create child nodes for each field added, e.g. rather than:
<links
link="[Example|http://example.com,Google|http://google.com]"/>
You would end up with:
<links>
<link_1
title="Example"
url="http://example.com"/>
<link_2
title="Google"
url="http://google.com"/>
<links>
You can read the values back without needing to parse them from a String value. It also means that things like rollout which update pathfields should work as standard.
The code is too long to produce here in full, but there's a nice starting point of this on the Adobe forums here. (It has an Adobe copyright notice, but posted by a user — not sure of it's official status, but good as a reference implementation; EDIT: possibly related to the Citytechnic MultiCompositeField on Github, as spotted by ery).
The sample above also takes the same approach as the multifield itself — i.e. it reads from a fieldConfig
node of the composite & creates a property for each entry on the child nodes it creates.
This makes the composite field completely reusable, as you only need one composite XType no matter how many variations you want to create, i.e. it would allow you to take the approach you outline in the question:
<links
jcr:primaryType="cq:Widget"
fieldLabel="QuickLinks"
name="./links"
xtype="mtmulticompositefield">
<fieldConfigs jcr:primaryType="cq:WidgetCollection">
<title
jcr:primaryType="cq:Widget"
fieldLabel="Title"
hideLabel="{Boolean}false"
name="./jcr:title"
xtype="textfield"/>
<url
jcr:primaryType="cq:Widget"
fieldLabel="URL"
name="./jcr:url"
xtype="textfield"/>
</fieldConfigs>
</links>
It also allows you to use more complex XTypes as children, e.g. images, without any further work.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With