Coral UI select multiple field can't remove all value

Avatar

Avatar

bhoang

Avatar

bhoang

bhoang

04-09-2018

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.

select-multiple-field.PNG

after that I go to "Views properties" to edit that field and remove selected value.

select-multiple-field-2.PNG

When I save it comeback again.

select-multiple-field.PNG

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.

select-multiple-field-3.PNG

I remove one option and save it work fine.

select-multiple-field.PNG

If I select 2 options and remove all and save, it back to.

select-multiple-field-3.PNG

My code to bind data into select field and check option fields as below.

The Json data as below: http://localhost:4502/.propertybenefits.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 + "/.propertybenefits.json/";

        var benefitSelectedValue = benefitProperty.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 = benefitProperty.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) {

$("#benefitProperty > coral-select-item").remove();

var x = document.getElementById("benefitProperty");

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,

BienHV

Accepted Solutions (1)

Accepted Solutions (1)

Avatar

Avatar

bhoang

Avatar

bhoang

bhoang

09-09-2018

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 = "benefitProperty" <%= 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>

benefitProperty._onSelectionChange = function(){

        setTimeout(function(){

            var coralTaglist = $("#benefitProperty > [name='./propertiesBenefits']")

            if(benefitProperty._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>

Answers (14)

Answers (14)

Avatar

Avatar

bhoang

Avatar

bhoang

bhoang

04-09-2018

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.

Avatar

Avatar

smacdonald2008

Total Posts

(val/1000)?string[".0"]}K

Likes

(val/1000)?string[".0"]}K

Correct Answer

(val/1000)?string[".0"]}K

Avatar

smacdonald2008

Total Posts

(val/1000)?string[".0"]}K

Likes

(val/1000)?string[".0"]}K

Correct Answer

(val/1000)?string[".0"]}K
smacdonald2008

04-09-2018

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.

Avatar

Avatar

smacdonald2008

Total Posts

(val/1000)?string[".0"]}K

Likes

(val/1000)?string[".0"]}K

Correct Answer

(val/1000)?string[".0"]}K

Avatar

smacdonald2008

Total Posts

(val/1000)?string[".0"]}K

Likes

(val/1000)?string[".0"]}K

Correct Answer

(val/1000)?string[".0"]}K
smacdonald2008

04-09-2018

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.

Avatar

Avatar

bhoang

Avatar

bhoang

bhoang

04-09-2018

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

Avatar

Avatar

smacdonald2008

Total Posts

(val/1000)?string[".0"]}K

Likes

(val/1000)?string[".0"]}K

Correct Answer

(val/1000)?string[".0"]}K

Avatar

smacdonald2008

Total Posts

(val/1000)?string[".0"]}K

Likes

(val/1000)?string[".0"]}K

Correct Answer

(val/1000)?string[".0"]}K
smacdonald2008

04-09-2018

As we stated - replace your datasource with the article that Ratna pointed you too that uses WCMUsePojo!

Avatar

Avatar

smacdonald2008

Total Posts

(val/1000)?string[".0"]}K

Likes

(val/1000)?string[".0"]}K

Correct Answer

(val/1000)?string[".0"]}K

Avatar

smacdonald2008

Total Posts

(val/1000)?string[".0"]}K

Likes

(val/1000)?string[".0"]}K

Correct Answer

(val/1000)?string[".0"]}K
smacdonald2008

04-09-2018

Your issue is not reproducible. AEM does let you save with no values - see:

Avatar

Avatar

bhoang

Avatar

bhoang

bhoang

04-09-2018

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()));
   }

}

Avatar

Avatar

bhoang

Avatar

bhoang

bhoang

04-09-2018

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.

Avatar

Avatar

smacdonald2008

Total Posts

(val/1000)?string[".0"]}K

Likes

(val/1000)?string[".0"]}K

Correct Answer

(val/1000)?string[".0"]}K

Avatar

smacdonald2008

Total Posts

(val/1000)?string[".0"]}K

Likes

(val/1000)?string[".0"]}K

Correct Answer

(val/1000)?string[".0"]}K
smacdonald2008

04-09-2018

See the following video that shows this working when using WCMUsePojo

Avatar

Avatar

smacdonald2008

Total Posts

(val/1000)?string[".0"]}K

Likes

(val/1000)?string[".0"]}K

Correct Answer

(val/1000)?string[".0"]}K

Avatar

smacdonald2008

Total Posts

(val/1000)?string[".0"]}K

Likes

(val/1000)?string[".0"]}K

Correct Answer

(val/1000)?string[".0"]}K
smacdonald2008

04-09-2018

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.

Avatar

Avatar

Ratna_Kumar

MVP

Avatar

Ratna_Kumar

MVP

Ratna_Kumar
MVP

04-09-2018

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.

Avatar

Avatar

Arun_Patidar

MVP

Total Posts

(val/1000)?string[".0"]}K

Likes

958

Correct Answer

820

Avatar

Arun_Patidar

MVP

Total Posts

(val/1000)?string[".0"]}K

Likes

958

Correct Answer

820
Arun_Patidar
MVP

04-09-2018

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

Avatar

Avatar

bhoang

Avatar

bhoang

bhoang

04-09-2018

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();
   }

}

Avatar

Avatar

Arun_Patidar

MVP

Total Posts

(val/1000)?string[".0"]}K

Likes

958

Correct Answer

820

Avatar

Arun_Patidar

MVP

Total Posts

(val/1000)?string[".0"]}K

Likes

958

Correct Answer

820
Arun_Patidar
MVP

04-09-2018

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