Hi Friends,
I am using selected multiple field. But it have problem, when I remove all values that I selected and save it. It can't save with none value selected.
Example: I selected one value and save ok.
after that I go to "Views properties" to edit that field and remove selected value.
When I save it comeback again.
If I selected more than one options and save. After that I remove some option and keep one or more than one selected and save, it work fine. If I remove all options and save it, It come back the option before I remove.
Example: I select 2 options and save ok.
I remove one option and save it work fine.
If I select 2 options and remove all and save, it back to.
My code to bind data into select field and check option fields as below.
The Json data as below: http://localhost:4502/.abcbenefits.json/
[{"id":"1","description":"asdf à","langCode":"en"},{"id":"2","description":"asdf ádf","langCode":"en"},{"id":"3","description":"adsf sadf","langCode":"en"}]
<script>
$(document).ready(function(){
var host_url = window.location.protocol + "//" + window.location.host + "/.abcbenefits.json/";
var benefitSelectedValue = abcbenefits.values;
// load property check on edit page or created page.
var pageNameID = document.getElementById("cq-sites-properties-form");
// is create page
if(pageNameID === null) {
//loadServiceDataFromURL(host_url);
}
// is edit page
else {
benefitSelectedValue = abcbenefits.values;
loadServiceDataFromURL(host_url);
}
function loadServiceDataFromURL(host_url) {
$.ajax(host_url, {
dataType: "json",
contentType: "application/json",
async: false,
success: function(rawData, status, xhr) {
try {
benefitBindData(rawData);
} catch (err) {
console.log(err);
}
},
error: function (xhr, status, err) {
console.log(err);
}
});
}
function benefitBindData(data) {
$("#abcbenefits> coral-select-item").remove();
var x = document.getElementById("abcbenefits");
var selectedItem = [];
data.forEach(function(item) {
var option = document.createElement("coral-select-item");
option.innerHTML = item["description"];
option.value = item["id"];
x.appendChild(option);
if (isSelectedBenefit(item["id"], benefitSelectedValue)) {
//option.selected = true;
selectedItem.push(option); //push selected item into an array
}
});
setTimeout(function(_selectedItems){
_selectedItems.forEach(function(option) {
option.selected = true;
});
}, 100, selectedItem)
}
function isSelectedBenefit(benefitId, benefitSelectedValues){
for(var i = 0; i < benefitSelectedValues.length;i++){
if(benefitId == benefitSelectedValues[i]) return true;
}
return false;
}
});
</script>
Please help me,
Thank you so much,
Solved! Go to Solution.
Views
Replies
Total Likes
I created a custom field for select and change the render.jsp file of the custom select field. So, I coded a JavaScript function to check the onchange of the select field. It work fine.
%><coral-select id = "abcProperty" <%= attrs.build() %>><%
if (cfg.get("emptyOption", false)) {
String value = "";
AttrBuilder opAttrs = new AttrBuilder(null, xssAPI);
opAttrs.add("value", value);
opAttrs.addSelected(cmp.getValue().isSelected(value, false));
out.println("<coral-select-item " + opAttrs.build() + "></coral-select-item>");
}
for (Iterator<Resource> items = itemIterator; items.hasNext();) {
printOption(out, items.next(), cmp);
}
%></coral-select><%!
<script>
abcProperty._onSelectionChange = function(){
setTimeout(function(){
var coralTaglist = $("#abcProperty> [name='./propertiesBenefits']")
if(abcProperty._oldSelection.length == 0){
coralTaglist.append("<input id = \"hiddenProperty\" handle=\"input\" type=\"hidden\" name=\"./propertiesBenefits\" value=\"\">");
coralTaglist[0].hidden = true;
}
else{
coralTaglist[0].hidden = false;
}
}, 100);
};
</script>
Hi,
I would suggest you to first try to populate dropdown using datasource instead of DOM manipulation.
Adobe Experience Manager Help | Using Granite DataSource objects to populate AEM Touch UI objects
Thanks
Arun
Views
Replies
Total Likes
I used the datasoure but it have that bug. This is my datasource.
<%@page session="false" import="
org.apache.sling.api.resource.Resource,
org.apache.sling.api.resource.ResourceUtil,
org.apache.sling.api.resource.ValueMap,
org.apache.sling.api.resource.ResourceResolver,
org.apache.sling.api.resource.ResourceMetadata,
org.apache.sling.api.wrappers.ValueMapDecorator,
java.util.List,
java.util.ArrayList,
java.util.HashMap,
java.util.Locale,
com.adobe.granite.ui.components.ds.DataSource,
com.adobe.granite.ui.components.ds.EmptyDataSource,
com.adobe.granite.ui.components.ds.SimpleDataSource,
com.adobe.granite.ui.components.ds.ValueMapResource,
com.day.cq.wcm.api.Page,
com.day.cq.wcm.api.PageManager,
com.abc.my.core.dto.PropertyAdminDto"%><%
%><%@taglib prefix="cq" uri="http://www.day.com/taglibs/cq/1.0" %><%
%><cq:defineObjects/><%
// set fallback
request.setAttribute(DataSource.class.getName(), EmptyDataSource.instance());
ResourceResolver resolver = resource.getResourceResolver();
// Create an ArrayList to hold data
List<Resource> resourceList = new ArrayList<Resource>();
ValueMap vm = null;
com.abc.my.core.models.datasource.PropertiesDataSource propertiesDataSource = new com.abc.my.core.models.datasource.PropertiesDataSource();
ArrayList<PropertyAdminDto> propertyList = propertiesDataSource.getData(resolver, request);
for (int i = 0; i < propertyList.size(); i++) {
// allocate memory to the Map instance
vm = new ValueMapDecorator(new HashMap<String, Object>());
// Specify the value and text values
String value = propertyList.get(i).getPropertyId();
String text = propertyList.get(i).getPropertyName();
// populate the map
vm.put("value", value);
vm.put("text", text);
resourceList.add(new ValueMapResource(resolver, new ResourceMetadata(), "nt:unstructured", vm));
}
//Create a DataSource that is used to populate the drop-down control
DataSource ds = new SimpleDataSource(resourceList.iterator());
request.setAttribute(DataSource.class.getName(), ds);
%>
core\models\datasource\BenefitsDataSource.java
package com.abc.my.core.models.datasource;
import com.abc.my.core.dto.BenefitsDto;
import com.abc.my.core.dto.BenefitsResponseDto;
import com.abc.my.core.dto.PropertyAdminDto;
import com.abc.my.core.dto.ResponseDto;
import com.abc.my.core.models.HostConfigUtill;
import com.abc.my.core.utility.ApiManagementConfiguration;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.mashape.unirest.http.Unirest;
import com.mashape.unirest.http.exceptions.UnirestException;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.wrappers.SlingHttpServletRequestWrapper;
import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.List;
public class BenefitsDataSource {
private static final String URL = "benefit/get?langCode=";
public static ArrayList<BenefitsDto> getData(ResourceResolver resourceResolver, HttpServletRequest request) {
Gson gson = new Gson();
String responseData = "default";
//get language code
String langCode = ((SlingHttpServletRequestWrapper) request).getRequest().getLocale().getLanguage();
ApiManagementConfiguration serviceHost = HostConfigUtill.getHost(resourceResolver);
try {
responseData = Unirest.get(serviceHost.getHost() + URL + langCode).headers(serviceHost.toHeaderMap()).asString().getBody();
} catch (UnirestException e) {
e.printStackTrace();
}
ResponseDto<BenefitsResponseDto> data = gson.fromJson(responseData, new TypeToken<ResponseDto<BenefitsResponseDto>>() {}.getType());
return data.getContent().getBenefitDtos();
}
}
Views
Replies
Total Likes
Hi,
Can you try to create a sling servlet and registered with resourceType and use this resource type in datasource node.
Inside Sling servlet you can make a ajax request to get json and parse that json and convert into ValueMap and add to datasource.
Example :
https://github.com/arunpatidar02/aem63app-repo/blob/master/java/HelloWorldCompDDServlet.java
Views
Replies
Total Likes
Hi,
You can use WCMUsePojo class to populate the dropdown.
Check this HELPX article: Adobe Experience Manager Help | Using an WCMUsePojo class to populate an Experience Manager Touch UI...
Thanks,
Ratna Kumar.
Views
Replies
Total Likes
Look at the Article that Ratna pointed you too. You can populate a Select Drop down via the WCMUsePojo class. This works! Manipulating the DOM via JS you showed is not best practice.
Views
Replies
Total Likes
See the following video that shows this working when using WCMUsePojo
Views
Replies
Total Likes
I know, I think that bug by AEM. Because, If I deleted many options and keep one options it work fine. If I remove all options it doesn't work.
Thank you for your help.
Views
Replies
Total Likes
Yes,
Before I put my question into this. I was created datasource, sling servlet to do that. It work fine, but have an error when I delete all options.
This is my servlet.
package com.abc.my.core.servlets;
import com.abc.my.core.dto.BenefitsDto;
import com.abc.my.core.dto.BenefitsResponseDto;
import com.abc.my.core.dto.ResponseDto;
import com.abc.my.core.models.HostConfigUtill;
import com.abc.my.core.utility.ApiManagementConfiguration;
import com.google.gson.Gson;
import com.google.gson.reflect.TypeToken;
import com.mashape.unirest.http.Unirest;
import com.mashape.unirest.http.exceptions.UnirestException;
import org.apache.sling.api.SlingHttpServletRequest;
import org.apache.sling.api.SlingHttpServletResponse;
import org.apache.sling.api.resource.ResourceResolver;
import org.apache.sling.api.servlets.HttpConstants;
import org.apache.sling.api.servlets.SlingAllMethodsServlet;
import org.apache.sling.api.servlets.SlingSafeMethodsServlet;
import org.apache.sling.api.wrappers.SlingHttpServletRequestWrapper;
import org.osgi.framework.Constants;
import org.osgi.service.component.annotations.Component;
import javax.servlet.Servlet;
import javax.servlet.ServletException;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
/**
* Servlet that writes some sample content into the response. It is mounted for
* all resources of a specific Sling resource type. The
* {@link SlingSafeMethodsServlet} shall be used for HTTP methods that are
* idempotent. For write operations use the {@link SlingAllMethodsServlet}.
*/
@Component(service=Servlet.class,
property={
Constants.SERVICE_DESCRIPTION + " = Property Benefits Servlet",
"sling.servlet.methods=" + HttpConstants.METHOD_GET,
"sling.servlet.selectors=propertybenefits",
"sling.servlet.resourceTypes="+ "sling/servlet/default",
"sling.servlet.extensions=" + "json"
})
public class PropertyBenefitsServlet extends SlingSafeMethodsServlet {
private static final Gson gson = new Gson();
private static final String URL = "benefit/get?langCode=";
@Override
protected void doGet(SlingHttpServletRequest req, SlingHttpServletResponse resp) throws ServletException, IOException {
ResourceResolver resourceResolver = req.getResourceResolver();
ApiManagementConfiguration serviceHost = HostConfigUtill.getHost(resourceResolver);
String langCode = ((SlingHttpServletRequestWrapper) req).getRequest().getLocale().getLanguage();
String responseData = "default";
try {
responseData = Unirest.get(serviceHost.getHost() + URL + langCode).headers(serviceHost.toHeaderMap()).asString().getBody();
}catch (Exception e) {
e.printStackTrace();
}
ResponseDto<BenefitsResponseDto> data = gson.fromJson(responseData, new TypeToken<ResponseDto<BenefitsResponseDto>>() {}.getType());
resp.setContentType("application/json");
resp.getWriter().write(gson.toJson(data.getContent().getBenefitDtos()));
}
}
Views
Replies
Total Likes
Your issue is not reproducible. AEM does let you save with no values - see:
Views
Replies
Total Likes
As we stated - replace your datasource with the article that Ratna pointed you too that uses WCMUsePojo!
Views
Replies
Total Likes
When I click on anny position in the Coral UI form. It show an error
VM552:1 Uncaught SyntaxError: Unexpected token s in JSON at position 0
at JSON.parse (<anonymous>)
at receiveMessage (clientlibs.js:60)
When I click on clientlibs.js it goto the line code that happen the error as below.
/**
* Receive two-part messages from the TemplatePicker dialog. The "data" part indicates the
* template picker path should be updated; the "config" part indicates whether or not the
* dialog should be closed.
*/
function receiveMessage(event) {
if (event.origin !== location.origin) {
return;
}
var fromTemplateBrowser = JSON.parse(event.data);
if (fromTemplateBrowser.sender !== "templatebrowser") {
return;
}
if (fromTemplateBrowser.data) {
var $sink = $templatePicker.data("sink"),
path = fromTemplateBrowser.data.path;
$sink.val(path).change();
}
if (fromTemplateBrowser.config) {
var action = fromTemplateBrowser.config.action;
if (action === 'close' || action === 'done') {
$templatePicker.data("modal").hide();
}
}
}
Do you have anny idea for this. This bug have effect to remove all option in multiple select field?
Thank you so much,
BienHV
Views
Replies
Total Likes
Have you tried using the logic in the article - Adobe Experience Manager Help | Using an WCMUsePojo class to populate an Experience Manager Touch UI...
As I showed in the 2nd video - this issue does not appear when using this Java logic.
Views
Replies
Total Likes
YOu may have found a bug. IN your sample - you are using JSON and in mine - we are using a MAP and DataSource which is populating the Select field. As i showed in video - i am not experiencing your reported issue. I can save the dialog with no options.
Views
Replies
Total Likes
I only used DataSource. But the bug still happen. If I remove many options and hole one option it work. If I remove all options it doesn't work. It back to the previous save.
Views
Replies
Total Likes
I created a custom field for select and change the render.jsp file of the custom select field. So, I coded a JavaScript function to check the onchange of the select field. It work fine.
%><coral-select id = "abcProperty" <%= attrs.build() %>><%
if (cfg.get("emptyOption", false)) {
String value = "";
AttrBuilder opAttrs = new AttrBuilder(null, xssAPI);
opAttrs.add("value", value);
opAttrs.addSelected(cmp.getValue().isSelected(value, false));
out.println("<coral-select-item " + opAttrs.build() + "></coral-select-item>");
}
for (Iterator<Resource> items = itemIterator; items.hasNext();) {
printOption(out, items.next(), cmp);
}
%></coral-select><%!
<script>
abcProperty._onSelectionChange = function(){
setTimeout(function(){
var coralTaglist = $("#abcProperty> [name='./propertiesBenefits']")
if(abcProperty._oldSelection.length == 0){
coralTaglist.append("<input id = \"hiddenProperty\" handle=\"input\" type=\"hidden\" name=\"./propertiesBenefits\" value=\"\">");
coralTaglist[0].hidden = true;
}
else{
coralTaglist[0].hidden = false;
}
}, 100);
};
</script>
Views
Replies
Total Likes
Hi bhoang!
Thank you for your good problem description and the solution. It worked for me.
I just needed to change two coral-select properties:
onchange instead of _onSelectionChange
values instead of _oldSelection
I guess it is because of the differences between the Coral UI versions.
Your script with these changes stayed like this:
<script>
benefitProperty.onchange = function(){
setTimeout(function(){
var coralTaglist = $("#benefitProperty > [name='./propertiesBenefits']")
if(benefitProperty.values.length == 0){
coralTaglist.append("<input id = \"hiddenProperty\" handle=\"input\" type=\"hidden\" name=\"./propertiesBenefits\" value=\"\">");
coralTaglist[0].hidden = true;
}
else{
coralTaglist[0].hidden = false;
}
}, 100);
};
</script>
Thank you again!
Views
Replies
Total Likes
Views
Replies
Total Likes
Views
Like
Replies
Views
Likes
Replies
Views
Likes
Replies
Views
Likes
Replies
Views
Likes
Replies