使用 JavaScript 中的索引获取 Spring 模型属性列表元素

问题描述 投票:0回答:4

很抱歉,如果在其他地方有人问过这个问题,但我环顾四周,找到了一些答案,但不是一个完整的例子,我仍然对此表示怀疑。

因此,我将一个自动填充列表从我的 Spring 控制器添加到我的 JSP,并且我想在我的 JavaScript / jQuery 函数内的列表中添加项目。可以吗?

我尝试了下面的代码来测试功能,但它不起作用(列表元素在生成的 html 中根本没有显示)。所以我不确定我是否搞乱了 JavaScript/Spring/JSP 语法,或者它是否根本不可能。


控制器代码:

@RequestMapping(value="/create_custobject.html",method = RequestMethod.GET)
public ModelAndView showCreateCustObjectPage() {
    Map<String, Object> model = new HashMap<String, Object>();
    
    CreateObjectForm form = new CreateObjectForm();
    model.put("createObjectform", form);
    
    return new ModelAndView("create_custobject", model) ;
    
}

表格代码:

public class CreateObjectForm {

      private AutoPopulatingList<Criteria> ruleArray = new AutoPopulatingList<Criteria>(Criteria.class);

     public AutoPopulatingList<Criteria> getRuleArray() {
    return ruleArray;
        }

         public void setRuleArray(AutoPopulatingList<Criteria> ruleArray) {
    this.ruleArray = ruleArray;
        }

         public CreateObjectForm() {}
      }

标准代码:

public class Criteria{

   String attribute;

    String operator;
       //... constructor + getters and setters
}

JavaScript / jQuery 代码(与 JSP 位于同一页面):

<script type="text/javascript">
$(document).ready(function(){
    //startup functionality

 var i = 0;
 document.getElementById("addCriteria").onclick = function() {

         $("#msgid").html("${ruleArray[i].attribute}");

        ${ruleArray[i].attribute} = $('#attributeValue').val();             
        ${ruleArray[i].operator} = $('#operatorValue').val(); 

                    i++;            

      }
   }
java javascript jquery spring spring-mvc
4个回答
3
投票

对于表单中的现有项目,请使用 jstl 作为

<c:forEach items="${form.items}" var="item" varStatus="status" >
<span class="count" > 
<form:input   path="items[${status.index}].field" />

这将呈现这样的形式

<form id = "idform" >
<span class="count" > 
    <input   name="items[0].field"  id="items0.field" />
</span>
</form>

然后你只需使用 javascript 添加新的表单“lines”和相应的索引

例如

 var is = $('.count').size()
 $('#idform span:last').after('<span class="count" ><input name="items[' + is + '].field"' + is + '.field" /></span>')

我认为如果你使用的是 spring 3 + 你不需要使用 AutopopulatedList ,任何集合就足够了。


1
投票

您混合 JSP EL 和 Javascript 的方式不正确。您不能在 JSP 表达式中使用

var i
,即。
${ruleArray[i].operator}
。我建议使用 JSTL 迭代列表并在脚本中创建属性。

此时,您的脚本可以设置为仅在表达式中使用字符串文字

0
。我假设您需要比这更强大的功能,您能更好地描述它吗?

$(document).ready(function(){
     document.getElementById("addCriteria").onclick = function() {

     $("#msgid").html("${ruleArray[0].attribute}");

     //I assume you wanted to set the element to the value pulled from JSP EL
     $('#attributeValue').val(${ruleArray[0].attribute});           
     $('#operatorValue').val(${ruleArray[0].operator});           

     }
 }

使用 JSTL,解决方案将类似于:

<script>
 var criteria = [];
 <c:forEach var="criteria" items=${ruleArray}>
    criteria.push({attr:${criteria.attribute}, oper: ${criteria.operator});
 </c:forEach>

 for(var i = 0; i < criteria.length; i++){
  alert(criteria[i].attribute);
 }
</script>

这个解决方案基本上使用JSTL来编写Javascript。修改控制器以返回 JSON 并在页面加载时进行 Ajax 调用可能是更好的解决方案。


0
投票

在下面的行中,您在 jsp 代码中引用

i
,但 i 未定义:

$("#msgid").html("${ruleArray[i].attribute}");

定义

i
的javascript代码在客户端(即浏览器)上执行。 jsp 代码在服务器上执行,然后将渲染的 html 发送到客户端。


0
投票

尽管该线程较旧且答案正确,但为了其他初学者的利益,并解释实现删除添加行的逻辑。

让我用最少的代码和带有 firstName、email、userName 和 sex 字段的用户示例来解释。
考虑到您从控制器发送 usersList 中的 3 个空用户,这将创建 3 个空行。现在您想要添加行并将添加的行动态绑定到 modelAttribute。

(如果是最初 3 行)如果您检查/查看页面源代码,您将看到

  • 行(
    <input> tags
    )具有不同的id,例如
    list0.firstName
    list1.firstName

  • 行(
    <input> tags
    )具有不同的名称,例如
    list[0].firstName
    list[1].firstName

每当提交表单时,服务器不会考虑id's(添加仅用于帮助客户端验证),但name属性将被解释为请求参数并用于构造您的modelAttribute,因此属性名称在插入时非常重要行。

添加行

那么,如何构造/追加新行?
如果我从 UI 提交 6 个用户,控制器应该从 usersList 接收 6 个用户对象。下面给出了实现相同目标的步骤
1. 右键

->
查看页面源。您将看到这样的行(您可以在第一行看到
*[0].*
,在第二行看到
*[1].*

<tr>
    <td><input id="list0.firstName" name="list[0].firstName" type="text" value=""/></td>
    <td><input id="list0.email" name="list[0].email" type="text" value=""/></td>
    <td><input id="list0.userName" name="list[0].userName" type="text" value=""/></td>
    <td>
        <span>
            <input id="list0.gender1" name="list[0].gender" type="radio" value="MALE" checked="checked"/>Male
        </span>
        <span>
            <input id="list0.gender2" name="list[0].gender" type="radio" value="FEMALE"/>Female
        </span>
    </td>
</tr>

<tr>
    <td><input id="list1.firstName" name="list[1].firstName" type="text" value=""/></td>
    <td><input id="list1.email" name="list[1].email" type="text" value=""/></td>
    <td><input id="list1.userName" name="list[1].userName" type="text" value=""/></td>
    <td>
        <span>
            <input id="list1.gender1" name="list[1].gender" type="radio" value="MALE" checked="checked"/>Male
        </span>
        <span>
            <input id="list1.gender2" name="list[1].gender" type="radio" value="FEMALE"/>Female
        </span>
    </td>
</tr>
  1. 复制第一行并构造一个 JavaScript 字符串,并将“0”替换为变量名称索引。如下例所示
'<tr>'+
    '<td><input id="list'+ index +'.firstName" name="list['+ index +'].firstName" type="text" value=""/></td>'+
    '<td><input id="list'+ index +'.email" name="list['+ index +'].email" type="text" value=""/></td>'+
    ...
'</tr>';
  1. 将构造的行附加到
    <tbody>
    。提交表单时,行也会添加到 UI 中,新添加的行将在控制器中收到。

删除行

删除行有点复杂,我会尝试用最简单的方式解释

  • 假设您添加了 row0、row1、row2、row3、row4、row5
  • 删除第2行、第3行。不要只是隐藏该行,而是将其从 通过捕获事件来实现 DOM。
  • 现在 row0,row1,row4,row5 将被提交,但在控制器中你的 userList 将有 6 个用户对象,但 user[2].firstName 将为 null 并且 user[3].firstName 将为 null。
  • 因此,在您的控制器中迭代并检查 null 并删除 user。(使用迭代器不要使用foreach来删除用户对象)

发布代码以惠及初学者。

//  In Controller
@RequestMapping(value = "/app/admin/add-users", method = RequestMethod.GET)
public String addUsers(Model model, HttpServletRequest request)
{
    List<DbUserDetails> usersList = new ArrayList<>();

    ListWrapper userListWrapper = new ListWrapper();
    userListWrapper.setList(usersList);


    DbUserDetails user;
    for(int i=0; i<3;i++)
    {
        user = new DbUserDetails();
        user.setGender("MALE"); //Initialization of Radio button/ Checkboxes/ Dropdowns
        usersList.add(user);
    }


    model.addAttribute("userListWrapper", userListWrapper);
    model.addAttribute("roleList", roleList);

    return "add-users";
}

@RequestMapping(value = "/app/admin/add-users", method = RequestMethod.POST)
public String saveUsers(@ModelAttribute("userListWrapper") ListWrapper userListWrapper, Model model, HttpServletRequest request)
{
    List<DbUserDetails> usersList = userListWrapper.getList();
    Iterator<DbUserDetails> itr = usersList.iterator();

    while(itr.hasNext())
    {
        if(itr.next().getFirstName() == null)
        {
            itr.remove();
        }
    }

    userListWrapper.getList().forEach(user -> {
        System.out.println(user.getFirstName());
    });
    return "add-users";
}

//POJO
@Entity
@Table(name = "userdetails")
@XmlRootElement(name = "user")
public class DbUserDetails implements Serializable
{
    @Id
    @GeneratedValue(strategy = GenerationType.IDENTITY)
    private Integer id;
    private String  firstName;
    private String  userName;
    private String  email;
    private String  gender;

    //setters and getters
}

//list wrapper
public class ListWrapper
{
    private List<DbUserDetails> list;

    //setters and getters
}

在JSP中

<form:form method="post" action="${pageContext.request.contextPath}/app/admin/add-users" modelAttribute="userListWrapper">
    <table class="table table-bordered">
        <thead>
            <tr>
                <th><spring:message code="app.userform.firstname.label"/></th>
                <th><spring:message code="app.userform.email.label"/></th>
                <th><spring:message code="app.userform.username.label"/></th>
                <th><spring:message code="app.userform.gender.label"/></th>
            </tr>
        </thead>
        <tbody id="tbodyContainer">
            <c:forEach items="${userListWrapper.list}" var="user" varStatus="loop">
                <tr>
                    <td><form:input path="list[${loop.index}].firstName" /></td>
                    <td><form:input path="list[${loop.index}].email" /></td>
                    <td><form:input path="list[${loop.index}].userName" /></td>
                    <td>
                        <span>
                            <form:radiobutton path="list[${loop.index}].gender" value="MALE" /><spring:message code="app.userform.gender.male.label"/>
                        </span>
                        <span>
                            <form:radiobutton path="list[${loop.index}].gender" value="FEMALE" /><spring:message code="app.userform.gender.female.label"/>
                        </span>
                    </td>
                </tr>
            </c:forEach>
        </tbody>
    </table>
    <div class="offset-11 col-md-1">
        <button type="submit" class="btn btn-primary">SAVE ALL</button>     
    </div>
</form:form>

JSP中需要包含Javascript

var currentIndex = 3; //equals to initialRow (Rows shown on page load)
function addRow()
{
    var rowConstructed = constructRow(currentIndex++);
    $("#tbodyContainer").append(rowConstructed);
}

function constructRow(index)
{
    return '<tr>'+
    '<td><input id="list'+ index +'.firstName" name="list['+ index +'].firstName" type="text" value=""/></td>'+
    '<td><input id="list'+ index +'.email" name="list['+ index +'].email" type="text" value=""/></td>'+
    '<td><input id="list'+ index +'.userName" name="list['+ index +'].userName" type="text" value=""/></td>'+
    '<td>'+
        '<span>'+
            '<input id="list'+ index +'.gender1" name="list['+ index +'].gender" type="radio" value="MALE" checked="checked"/>Male'+
        '</span>'+
        '<span>'+
            '<input id="list'+ index +'.gender'+ index +'" name="list['+ index +'].gender" type="radio" value="FEMALE"/>Female'+
        '</span>'+
    '</td>'+
'</tr>';
}
© www.soinside.com 2019 - 2024. All rights reserved.