I've got the below textfield that authors use to input a property.
This gets saved in JCR as articleId.
<articleId
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
fieldLabel="Article Id"
name="./articleId"/>
I would like to create another property and save the same articleId value against it(cq:panelTitle in my case). Essentially maintaining two properties with the same value.
Trying to prevent the authors from filling an additional field.
How do i achieve this during dialog save ?
Thanks.
Solved! Go to Solution.
Views
Replies
Total Likes
Another way we can achieve this also , I am sharing touch ui dialog editor .context.xml here -
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:cq="http://www.day.com/jcr/cq/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="Application"
sling:resourceType="cq/gui/components/authoring/dialog">
<content
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/fixedcolumns">
<items jcr:primaryType="nt:unstructured">
<column
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/container">
<items jcr:primaryType="nt:unstructured">
<articleId
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
fieldLabel="Article Id"
name="./newarticleId"/>
<panelTitle
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/hidden"
defaultValue="./articleId"
fieldLabel="CQ Article Panel"
name="./cq:panelTitle@ValueFrom"
value="./articleId"/>
</items>
</column>
</items>
</content>
</jcr:root>
When a new value is saved for articleId, Sling will update automatically cq:panelTitle property via @ValueFrom suffix. It’s also important to use granite/ui/components/coral/foundation/form/hidden widget in order to work properly.
Only this much will be required at dialog editor only and we don't need anything.
Reference link: https://www.flexibledesigns.rs/automatic-update-of-a-dialog-field-based-on-the-value-of-another-fiel...
I have created below sample component for the same -
Here is .content.xml for touch ui dialog editor
<?xml version="1.0" encoding="UTF-8"?> <jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:cq="http://www.day.com/jcr/cq/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="Application" sling:resourceType="cq/gui/components/authoring/dialog"> <content jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/fixedcolumns"> <items jcr:primaryType="nt:unstructured"> <column jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/container"> <items jcr:primaryType="nt:unstructured"> <articleId jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/form/textfield" fieldLabel="Article Id" name="./articleId"/> <panelTitle jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/form/textfield" disabled="{Boolean}true" fieldLabel="CQ Article Panel" name="./cq:panelTitle"/> </items> </column> </items> </content> </jcr:root>
I have two text fields here and I just made ./cq:panelTitle disable so, author can't change the value of this field.
Sling model -
package com.aem.demo.core.models; import java.util.Objects; import javax.annotation.PostConstruct; import javax.jcr.Node; import javax.jcr.RepositoryException; import javax.jcr.Session; import javax.jcr.ValueFormatException; import javax.jcr.lock.LockException; import javax.jcr.nodetype.ConstraintViolationException; import javax.jcr.version.VersionException; import org.apache.sling.api.SlingHttpServletRequest; import org.apache.sling.models.annotations.DefaultInjectionStrategy; import org.apache.sling.models.annotations.Model; import org.apache.sling.models.annotations.injectorspecific.SlingObject; import org.apache.sling.models.annotations.injectorspecific.ValueMapValue; @Model(adaptables = SlingHttpServletRequest.class, defaultInjectionStrategy = DefaultInjectionStrategy.OPTIONAL) public class ArticleModel { @ValueMapValue private String articleId; @ValueMapValue (name = "cq:panelTitle") private String panel; @SlingObject SlingHttpServletRequest slingHttpServletRequest; @PostConstruct protected void init() { if (Objects.nonNull(articleId)) { panel = articleId; Node currentnode = slingHttpServletRequest.getResource().adaptTo(Node.class); Session session = slingHttpServletRequest.getResourceResolver().adaptTo(Session.class); try { currentnode.setProperty("cq:panelTitle", panel); session.save(); } catch (ValueFormatException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (VersionException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (LockException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (ConstraintViolationException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (RepositoryException e) { // TODO Auto-generated catch block e.printStackTrace(); } } } /** * @return the articleId */ public String getArticleId() { return articleId; } /** * @return the panel */ public String getPanel() { return panel; } }
Here I am reading the value of articleId and assign the same to cq:PanelTitle. This sling model is also helping to set the assigned value to cq:PanelTitle and store the same to aem repository as shown below -
HTL code to display the value-
ARTICLE <sly data-sly-use.article="com.aem.demo.core.models.ArticleModel"></sly> <h3>${article.articleId}</h3></br> <h3>${article.panel}</h3> </div>
Hope this will help.
we can hide cq:panelTitle field as well as shown below, if you don't want to show it to content authors -
The below sling model , htl code will be working as expected in this case also.
Hi @subsul1,
I think that the easiest option will be to create client lib with below js code that will simply copy articleId value into cq:panelTitle before dialog submit. Here is js you can use.
(function ($, $document) { "use strict"; $(document).on("click", ".cq-dialog-submit", function (e) { var articleIdValue = $("[name='./articleId']").val(); var cqPanelTitle = $("[name='./cq:panelTitle']").attr("value", articleIdValue); }); })($, $(document));
this assumes dialog structure like this:
<items jcr:primaryType="nt:unstructured"> <articleId jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/form/textfield" fieldLabel="Article Id" name="./articleId"/> <panelTitle jcr:primaryType="nt:unstructured" sling:resourceType="granite/ui/components/coral/foundation/form/textfield" disabled="{Boolean}true" fieldLabel="CQ Panel Title" name="./cq:panelTitle"/> </items>
Please remember to add extraClientlibs property in your dialog definition that will point to the clientlib with js definition.
<?xml version="1.0" encoding="UTF-8"?> <jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:cq="http://www.day.com/jcr/cq/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="Dialog title" extraClientlibs="[your.client.lib.category]" sling:resourceType="cq/gui/components/authoring/dialog">
You can also consider to use hidden filed for cq:panelTitle if you do not want to expose this filed to the author.
Alternatively you can create https://sling.apache.org/apidocs/sling5/org/apache/sling/servlets/post/SlingPostProcessor.html to handle it on backend side.
In my opinion you should avoid changing data on Sling Model level. Sling Model is to read/map data from repository.
@lukasz-m Thanks for taking time to answer my question. @DEBAL_DAS 's answer I feel is straight forward and does not require inclusion of extraClientlibs.
Anyway, your answer has helped me learn some more concepts within AEM. Thanks.
Another way we can achieve this also , I am sharing touch ui dialog editor .context.xml here -
<?xml version="1.0" encoding="UTF-8"?>
<jcr:root xmlns:sling="http://sling.apache.org/jcr/sling/1.0" xmlns:cq="http://www.day.com/jcr/cq/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="Application"
sling:resourceType="cq/gui/components/authoring/dialog">
<content
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/fixedcolumns">
<items jcr:primaryType="nt:unstructured">
<column
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/container">
<items jcr:primaryType="nt:unstructured">
<articleId
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/textfield"
fieldLabel="Article Id"
name="./newarticleId"/>
<panelTitle
jcr:primaryType="nt:unstructured"
sling:resourceType="granite/ui/components/coral/foundation/form/hidden"
defaultValue="./articleId"
fieldLabel="CQ Article Panel"
name="./cq:panelTitle@ValueFrom"
value="./articleId"/>
</items>
</column>
</items>
</content>
</jcr:root>
When a new value is saved for articleId, Sling will update automatically cq:panelTitle property via @ValueFrom suffix. It’s also important to use granite/ui/components/coral/foundation/form/hidden widget in order to work properly.
Only this much will be required at dialog editor only and we don't need anything.
Reference link: https://www.flexibledesigns.rs/automatic-update-of-a-dialog-field-based-on-the-value-of-another-fiel...
@DEBAL_DAS Thanks for taking time to answer my question. @ValueFrom approach is succinct and does the job very well.
Got to learn a few concepts from your answers. Thank you.
hi,
Why do you want to save same value in two properties? It is not good for maintaining purpose.
What do you want to achieve with this? There could be an another way.