Checkbox value persist - aem

I have 3 checkbox widget in my dialog & and on the basis of no of selection code perform the logic, Issue is when i tick option1 option2, then they set their value in the content node to "ON". But if i edit the same component option1, option2 are select , i unselect the one and click ok, Still in the content node property exist with value "ON".
<?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:Widget"
xtype="tabpanel">
<items jcr:primaryType="cq:WidgetCollection">
<tab1
jcr:primaryType="cq:Panel"
title="Select Options">
<items jcr:primaryType="cq:WidgetCollection">
<facebook
jcr:primaryType="cq:Widget"
fieldLabel="Facebook"
name="./facebook"
xtype="checkbox"/>
<twitter
jcr:primaryType="cq:Widget"
fieldLabel="Twitter"
name="./twitter"
xtype="checkbox"/>
<linkedin
jcr:primaryType="cq:Widget"
fieldLabel="Linkedin"
name="./linkedin"
xtype="checkbox"/>
</items>
</tab1>
</items>
</items>
</jcr:root>

I have not had a lot of success with the checkbox xtype. Rather, try the selection xtype, with a type of checkbox.
<facebook
jcr:primaryType="cq:Widget"
fieldLabel="Facebook"
name="./facebook"
type="checkbox"
xtype="selection"/>

the problem you have is that when you uncheck the checkbox, the form is simply not sending that field into the POST, so Sling simply does not modify that property at all.
To be able to persist the unchecked state you need to add default values. You can do that with Sling Suffixes.
parameter#Delete, causes a property to be deleted from jcr if no other value has been sent. in your case you could interpret no property as unchecked
parameter#DefaultValue can be used to send a default value in case parameter was sent without any value
parameter#UseDefaultWhenMissing = true, can be used to force Sling to use the default value when the parameter was not sent at all.
So, in your particular case, add hidden fields (xtype:hidden) with the following names & values.
./facebook#DefaultValue="off"
./facebook#UseDefaultWhenMissing="true"
That would make sure that the value "off" is used when the checkbox is unchecked.
ps-Yes, it is that annoying to use checkboxes in AEM/CQ

Related

AEM 6.2 - Set value in one dropdown based on selection of another dropdown value

In AEM 6.2, I have the first drop-down which has three values [x, y, z] and the second drop-down with these values [abc, def, ghk]. My requirement is that when I select the value [y] in the first drop-down, I want to disable the second drop-down and set the value as [def]. The author should not be able to change the value of the second drop-down when [y] is selected in the first down (it should be defaulted to [def]).
Disclaimer: This solution is not meant to be perfect, I tested it and it works on a vanilla installation of AEM 6.2 (no CFP or SP installed). The javascript API's may change with CFP's and SP's. However, the solution below should serve as a good foundation and with a bit of debugging you can make it work with your environment.
It seems like there was no good resources on the web, at-least not ones that do what you're asking properly, so I wrote a solution:
I created the following component:
HTML:
<h1> dropdown test placeholder</h1>
<h4>first: ${properties.first}</h4>
<h4>second: ${properties.second}</h4>
cq:dialog
Please note the following:
The root node of the dialog has extraClientlibs="[dropdown-author-clientlib]" this is our clientlib category where we will add the custom code
The dropdown nodes have id's id="first-dropdown" and id="first-dropdown" so we can easily select them in our code
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root
xmlns:jcr="http://www.jcp.org/jcr/1.0"
xmlns:cq="http://www.day.com/jcr/cq/1.0"
xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
xmlns:sling="http://sling.apache.org/jcr/sling/1.0"
jcr:primaryType="nt:unstructured"
jcr:title="Example Dialog"
sling:resourceType="cq/gui/components/authoring/dialog"
extraClientlibs="[dropdown-author-clientlib]">
<content jcr:primaryType="nt:unstructured"sling:resourceType="granite/ui/components/foundation/container">
<layout jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/foundation/layouts/fixedcolumns" />
<items jcr:primaryType="nt:unstructured">
<column jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/foundation/container">
<items jcr:primaryType="nt:unstructured">
<first jcr:primaryType="nt:unstructured" fieldLabel="First" id="first-dropdown" name="./first" sling:resourceType="granite/ui/components/foundation/form/select">
<items jcr:primaryType="nt:unstructured">
<default jcr:primaryType="nt:unstructured" text="(default)" value="" />
<x jcr:primaryType="nt:unstructured" text="x" value="x" />
<y jcr:primaryType="nt:unstructured" text="y" value="y" />
<z jcr:primaryType="nt:unstructured" text="z" value="z" />
</items>
</first>
<second jcr:primaryType="nt:unstructured" fieldLabel="second" id="second-dropdown" name="./second" sling:resourceType="granite/ui/components/foundation/form/select">
<items jcr:primaryType="nt:unstructured">
<def jcr:primaryType="nt:unstructured" text="def" value="def" />
<ghi jcr:primaryType="nt:unstructured" text="ghi" value="ghi" />
<abc jcr:primaryType="nt:unstructured" text="abc" value="abc" />
<default jcr:primaryType="nt:unstructured" text="(default)" value="" />
</items>
</second>
</items>
</column>
</items>
</content>
</jcr:root>
The clientlib:
Under the component, I created this clientlib:
categories="[dropdown-author-clientlib]"
I wont get into creating a clientlib, it's simple enough.
in the clientlib, I added the following script.js file:
(function(){
var $doc = $(document);
var $first, $second;
$doc.on('foundation-contentloaded', function(e) { // 'foundation-contentloaded' triggered when dialog is ready
$dialog = $(e.target);
// get "Coral UI 2" select instance reference: https://helpx.adobe.com/experience-manager/6-2/sites/developing/using/reference-materials/coral-ui/components/Coral.Select.html#
firstSelect = $dialog.find('#first-dropdown').data('select'); // coral ui select instance
secondSelect = $dialog.find('#second-dropdown').data('select'); // coral ui select instance
// enables/disables the second select based on value provided
function toggleSecond(firstVal){
if(firstVal === 'y'){
secondSelect._select('def', 'def'); // first is the value, second is the display text
secondSelect.set('disabled', true)
// we need to remove 'disabled' attr from the actul select inorder for it to be submitted with form submit
secondSelect.$element.find('select').removeAttr('disabled');
}
else {
secondSelect.set('disabled', false)
}
}
// run when dialog opens
toggleSecond(firstSelect.getValue());
// 'selected' is not in the documentation, change does not work, found this by looking into the js code
firstSelect.on('selected', function(e){
toggleSecond(e.selected);
})
});
})();
Now when you select y in the first dropdown, the second one will be set to 'def' and disabled.
The code above should be simple enough to follow, I added comments to make it even easier to follow. Let me know if you have any questions.

When Datepicker is a field in a multifield, the date is not displayed

I have datpicker in multifield.
But on opening the dialog the authored values are not getting displayed.
When i do inspect element on dialog field it comes as
*<input class="coral-InputGroup-input coral-Textfield" type="text" value="">
<input type="hidden" name="./date" value="2016-06-01T00:00:00.000+05:30">*
Can you please suggest what can be the issue and how to resolve it?
<field
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/form/fieldset"
eaem-nested=""
fieldLabel="Click on the + button to add Fields"
name="./admission">
<layout
jcr:primaryType="nt:unstructured"
sling:resouceType="granite/ui/components/foundation/layouts/fixedcolumns"
method="absolute"/>
<items jcr:primaryType="nt:unstructured">
<column
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/container">
<items jcr:primaryType="nt:unstructured">
<date
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/form/datepicker"
fieldLabel="Date of Event"
name="./date"
type="date"/>
<startTime
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/form/datepicker"
fieldLabel="Opening time of event"
name="./startTime"
type="time"/>
<endTime
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/form/datepicker"
fieldLabel="Closing time of event"
name="./endTime"
type="time"/>
<dayname
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/form/hidden"
fieldLabel="Dayname"
name="./dayname"/>
</items>
</column>
</items>
</field>
First of all, you have a misspelling in sling:resouceType="granite/ui/components/foundation/layouts/fixedcolumns". You effectively don't have a sling:resourceType set.
However, there's also a more important issue. The Granite Multifield component doesn't work this way. Reading the documentation on the granite/ui/components/foundation/form/multifield we can see exactly how the data is saved and repopulated on subsequent dialog openings.
The field to be included is defined in the subnode named field.
Regardless of the component used, Multifield assumes they all write to
the same property (defined by the name property of the field subnode)
thus the resulting value will always be multi value.
When rendering existing entries, the Multifield will iterate over the multi value, get each value, set it in the field and let the field render it.
In order to accomplish what you're looking to do, you will have to write some custom code. A quick Google search revealed this two blog posts that can help you:
http://experience-aem.blogspot.com/2015/06/aem-61-touch-ui-composite-multifield-store-values-as-child-nodes.html
http://experience-aem.blogspot.com/2015/02/aem-6-sp2-touch-ui-multi-field-component.html
To reiterate, if you fix your typo, the fieldset and datepickers will show in your multifield. However, even though the dialog will display correctly, you won't be able to save or retrieve the data in this manner.

cq5 AEM 'pathfield' resizing

I use xtype 'multifieldpanel' from ACS.CQ library for 'multifield configuration'. And I can't set size for 'pathfield' in my dialog. I need 100% (fixed size in 'px' doesn't work too) similar with 'textfield'. I have tried all cases (width, boxMaxWidth, autoWidth), what I do wrong??
<links
jcr:primaryType="cq:Widget"
fieldLabel="Items Location"
itemId="links"
name="./links"
xtype="multifield">
<fieldConfig
jcr:primaryType="nt:unstructured"
xtype="multifieldpanel">
<items jcr:primaryType="cq:WidgetCollection">
<title
jcr:primaryType="cq:Widget"
allowBlank="{Boolean}false"
fieldLabel="Title"
width="100%"
key="title"
xtype="textfield"/>
<url
jcr:primaryType="cq:Widget"
allowBlank="{Boolean}false"
fieldLabel="URL"
boxMaxWidth="100%"
key="url"
xtype="pathfield"/>
</items>
</fieldConfig>
In the dialog,you have to give properties for pathfield as follows
name:width
type:Long
value:(as required) for ex:500
Similarly for textfield also you can follow the above procedure
1.Create a node in your component of type cq:EditConfig and name cq:editConfig, this should be a sibling of the dialog node.
2.To the cq:editConfig node add a property with name “cq:dialogMode”, type “String” and value “floating”
3.To your dialog node add two properties of type Long, name height and width and value to what the you want the size of the dialog to be.
try autoWidth="true" style="width: 90%"

Allow blank value in AEM Touch UI multifield (select field)

I've created an AEM Touch UI multifield in a component dialog node. It has a sub-field of select. The select control contains a list of permissions. The idea is that an author can select multiple permissions and the user must have at least one of those permissions in order to see the component, or if no permissions are specified for that component, all users will see it. Below is the .content.xml file for the dialog tab (the tab gets included via granite/ui/components/foundation/include reference).
I can add new permissions to the multifield, change them, and remove them with one caveat: I can't remove the last permission in the list. For some reason, AEM isn't allowing me to have an empty multifield once I've selected something. I've tried setting allowBlank to true, but I don't think this property applies to the Touch UI--either way, it doesn't fix the issue.
How can I allow a content author to remove all items in the multifield?
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:jcr="http://www.jcp.org/jcr/1.0" xmlns:nt="http://www.jcp.org/jcr/nt/1.0"
jcr:primaryType="nt:unstructured"
jcr:title="Portal Filters"
sling:resourceType="granite/ui/components/foundation/container">
<items jcr:primaryType="nt:unstructured">
<permissions
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/form/multifield"
fieldDescription="A user must have at least one of these permissions to view this component"
fieldLabel="Permissions">
<field
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/form/select"
name="./permissions">
<datasource
jcr:primaryType="nt:unstructured"
sling:resourceType="/apps/mportal/datasources/permissions"/>
</field>
</permissions>
<missions
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/form/multifield"
fieldDescription="A user must have at least one of these missions to view this component"
fieldLabel="Missions">
<field
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/form/select"
name="./missions">
<datasource
jcr:primaryType="nt:unstructured"
sling:resourceType="/apps/mportal/datasources/missions"/>
</field>
</missions>
<mtcs
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/form/multifield"
fieldDescription="A user must have at least one of these mtcs to view this component"
fieldLabel="MTCs">
<field
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/form/select"
name="./mtcs">
<datasource
jcr:primaryType="nt:unstructured"
sling:resourceType="/apps/mportal/datasources/mtcs"/>
</field>
</mtcs>
<languages
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/form/multifield"
fieldDescription="A user must have at least one of these languages to view this component"
fieldLabel="Languages">
<field
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/form/select"
name="./languages">
<datasource
jcr:primaryType="nt:unstructured"
sling:resourceType="/apps/mportal/datasources/languages"/>
</field>
</languages>
<startdate
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/form/datepicker"
fieldLabel="Start Date"
name="./startdate"/>
<enddate
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/foundation/form/datepicker"
fieldLabel="End Date"
name="./enddate"/>
</items>
</jcr:root>
It turns out there is an issue with the way AEM Touch UI multifield components update values. If you remove the last item, the component sends no value up to the server (much like an unchecked checkbox). You have to explicitly tell AEM that you want to delete the value of a multifield if there are no items in it. Here's how:
At the same level as your multifield node, create a new node
(nt:unstructured); I call it permissions-delete (to correspond
with my multifield called permissions)
Add the following properties:
sling:resourceType, String, granite/ui/components/foundation/form/hidden
name, String, ./permissions#Delete (where ./permissions is the value of name field of the permissions/field node)
value, Boolean, true
Now when you remove the last item, the value of the hidden field will ensure that it is deleted and not just ignored.

Adding select dropdown to dialog window

I'm having difficulty on how to add options to a selection for dialog.
The Adobe notes I'm reading are here: CQ.form.Selection
Scrolling down to options : Object[]/String will show you two ways to reference the options to provide the said selection, via object or string. I am trying to use the object method. The format example they provide is sufficient.
[
{
value: "pink", // all types except "combobox"
text: "Pink",
qtip: "Real Pink" // "select" and "combobox"
}
]
However, CRXDE Lite does not allow me to select or type Object when adding a new property, and this is where I am at a loss. Is there another way to enter a complex value?
Adding options as an Object[] would be done via a child node, rather than properties. (In fact anywhere you see an Object in the API, think node rather than property.)
In your dialog.xml file, this would be done as follows:
<selectList
jcr:primaryType="cq:Widget"
defaultValue="0"
fieldLabel="Number"
name="./number"
type="select"
xtype="selection">
<options jcr:primaryType="cq:WidgetCollection">
<one
jcr:primaryType="nt:unstructured"
text="One"
value="1"/>
<two
jcr:primaryType="nt:unstructured"
text="Two"
value="2"/>
<three
jcr:primaryType="nt:unstructured"
text="Three"
value="3"/>
<four
jcr:primaryType="nt:unstructured"
text="Four"
value="4"/>
</options>
</selectList>
In CRXDE, this can be achieved by creating the same hierarchy:
Right-clicking your selection node and choosing Create > Node.
Give this node a jcr:primaryType of cq:WidgetCollection. This will hold your option values.
Individual options can now be added as child nodes of this, with a jcr:primaryType of nt:unstructured.
Place your properties (value, text, qtip) on these child nodes.