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

12.7K

Likes

1.4K

Correct Reply

2.3K

Avatar

smacdonald2008

Total Posts

12.7K

Likes

1.4K

Correct Reply

2.3K
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

12.7K

Likes

1.4K

Correct Reply

2.3K

Avatar

smacdonald2008

Total Posts

12.7K

Likes

1.4K

Correct Reply

2.3K
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

12.7K

Likes

1.4K

Correct Reply

2.3K

Avatar

smacdonald2008

Total Posts

12.7K

Likes

1.4K

Correct Reply

2.3K
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

12.7K

Likes

1.4K

Correct Reply

2.3K

Avatar

smacdonald2008

Total Posts

12.7K

Likes

1.4K

Correct Reply

2.3K
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

12.7K

Likes

1.4K

Correct Reply

2.3K

Avatar

smacdonald2008

Total Posts

12.7K

Likes

1.4K

Correct Reply

2.3K
smacdonald2008

04-09-2018

See the following video that shows this working when using WCMUsePojo

Avatar

Avatar

smacdonald2008

Total Posts

12.7K

Likes

1.4K

Correct Reply

2.3K

Avatar

smacdonald2008

Total Posts

12.7K

Likes

1.4K

Correct Reply

2.3K
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

3.1K

Likes

1.2K

Correct Reply

883

Avatar

Arun_Patidar

MVP

Total Posts

3.1K

Likes

1.2K

Correct Reply

883
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

3.1K

Likes

1.2K

Correct Reply

883

Avatar

Arun_Patidar

MVP

Total Posts

3.1K

Likes

1.2K

Correct Reply

883
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