You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Liferay 7新手开发者求助:实现组织机构级联下拉选择框

实现Liferay 7中组织机构联动下拉框

嘿,作为Liferay 7的新手,你已经成功迈出了第一步!接下来咱们一步步搞定依赖第一个下拉框的子组织机构选择功能,实现无刷新的联动效果~

一、后端修改:添加子机构资源接口

首先咱们需要在你的NetcofilmoPortlet中添加一个资源处理方法,用来接收前端传递的父机构ID,返回对应的子组织机构数据。Liferay的MVCPortlet通过serveResource方法处理AJAX这类资源请求,非常适合这个场景:

import com.liferay.portal.kernel.json.JSONArray;
import com.liferay.portal.kernel.json.JSONFactoryUtil;
import com.liferay.portal.kernel.json.JSONObject;
import com.liferay.portal.kernel.portlet.bridges.mvc.MVCPortlet;
import com.liferay.portal.kernel.util.PortalUtil;
import com.liferay.portal.kernel.util.StringUtils;
import com.liferay.portal.kernel.service.OrganizationLocalServiceUtil;
import com.liferay.portal.kernel.model.Organization;

import javax.portlet.ResourceRequest;
import javax.portlet.ResourceResponse;
import java.io.IOException;
import java.util.List;

public class NetcofilmoPortlet extends MVCPortlet {

    // 你原来的getOrga方法保留不变
    public List<Organization> getOrga() {
        Long companyId = PortalUtil.getCompanyIds()[0];
        Long parentOrgaId = OrganizationLocalServiceUtil.getOrganizationId(companyId, "Crédit Agricole");
        List<Organization> Siege = OrganizationLocalServiceUtil.getOrganizations(companyId, parentOrgaId);
        return Siege;
    }

    @Override
    protected void doDispatch(RenderRequest request, RenderResponse response) throws IOException, PortletException {
        request.setAttribute("listeOrganisations", getOrga());
        super.doDispatch(request, response);
    }

    // 新增:处理子机构AJAX请求的方法
    @Override
    public void serveResource(ResourceRequest request, ResourceResponse response) throws IOException, PortletException {
        super.serveResource(request, response);

        // 获取前端传递的父机构ID
        String parentOrgIdStr = request.getParameter("parentOrgId");
        if (StringUtils.isNotEmpty(parentOrgIdStr)) {
            Long parentOrgId = Long.parseLong(parentOrgIdStr);
            // 从请求中获取当前公司ID(比直接取数组第一个更健壮)
            Long companyId = PortalUtil.getCompanyId(request);

            // 查询该父机构下的子组织机构
            List<Organization> subOrganizations = OrganizationLocalServiceUtil.getOrganizations(companyId, parentOrgId);

            // 把数据转成JSON格式返回给前端
            JSONArray jsonArray = JSONFactoryUtil.createJSONArray();
            for (Organization org : subOrganizations) {
                JSONObject jsonObj = JSONFactoryUtil.createJSONObject();
                jsonObj.put("id", org.getOrganizationId());
                jsonObj.put("name", org.getName());
                jsonArray.put(jsonObj);
            }

            // 设置响应类型为JSON
            response.setContentType("application/json");
            response.getWriter().write(jsonArray.toString());
        }
    }
}

二、前端修改:实现AJAX联动

接下来修改前端代码,把原来的整页提交改成AJAX请求,动态渲染子机构下拉框:

<%@ taglib prefix="aui" uri="http://liferay.com/tld/aui" %>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %>
<%@ taglib prefix="portlet" uri="http://java.sun.com/portlet_2_0" %>

<!-- 第一个组织机构下拉框:修改onChange事件,调用自定义JS函数 -->
<aui:select name="Siege" onChange="loadSubOrganizations(this.value);" id="Siege">
    <aui:option value="" selected="true">---Select---</aui:option>
    <c:forEach var="organisation" items="${listeOrganisations}">
        <aui:option value="${organisation.organizationId}">${organisation.name}</aui:option>
    </c:forEach>
</aui:select>

<!-- 第二个子组织机构下拉框:初始仅显示默认选项 -->
<aui:select name="subOrga" id="subOrga">
    <aui:option value="" selected="true">---Select Sub Organization---</aui:option>
</aui:select>

<script type="text/javascript">
function loadSubOrganizations(parentOrgId) {
    // 获取子机构下拉框元素(注意加上Portlet命名空间,Liferay会自动生成)
    var subOrgaSelect = document.getElementById('<portlet:namespace />subOrga');
    
    // 清空现有选项,保留默认提示
    subOrgaSelect.innerHTML = '<option value="" selected="true">---Select Sub Organization---</option>';
    
    // 如果没有选择父机构,直接返回
    if (!parentOrgId) {
        return;
    }
    
    // 发送AJAX请求到Portlet的资源接口
    var xhr = new XMLHttpRequest();
    // 使用portlet标签生成资源请求URL
    xhr.open('POST', '<portlet:resourceURL />', true);
    xhr.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded');
    
    // 请求成功后的处理逻辑
    xhr.onload = function() {
        if (xhr.status === 200) {
            // 解析返回的JSON数据
            var subOrgs = JSON.parse(xhr.responseText);
            // 遍历子机构数据,动态添加选项
            subOrgs.forEach(function(org) {
                var option = document.createElement('option');
                option.value = org.id;
                option.textContent = org.name;
                subOrgaSelect.appendChild(option);
            });
        }
    };
    
    // 发送请求参数:父机构ID
    xhr.send('parentOrgId=' + encodeURIComponent(parentOrgId));
}
</script>

三、关键注意事项

  • Portlet命名空间:Liferay会为每个Portlet的表单元素添加唯一命名空间,所以JS中获取元素ID时必须用<portlet:namespace />前缀,否则会找不到元素。
  • CompanyId的获取:我把你原来的PortalUtil.getCompanyIds()[0]改成了PortalUtil.getCompanyId(request),这样能适配多公司场景,更健壮。
  • 依赖导入:确保你的Portlet项目中已经导入了JSONFactoryUtil、StringUtils等类的依赖,Liferay的内核包中已经包含这些类,不需要额外引入。

这样修改后,当你选择第一个下拉框的组织机构时,第二个下拉框就会自动加载对应的子组织机构,实现无刷新的联动效果啦!

内容的提问来源于stack exchange,提问作者Steve Diarrassouba

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 03:26:33