使用来自javascript的索引获取spring模型属性列表元素

时间:2012-11-13 10:20:37

标签: java javascript jquery spring spring-mvc

很抱歉,如果有人问过其他地方,但我已经四处寻找,找到了一些答案,但不是一个完整的例子,我仍然怀疑这个。

所以,我正在从我的Spring控制器添​​加一个Autopopulating列表到我的jsp,我想在我的javascript / jquery函数中的列表中添加项目。可能吗?

我尝试了下面的代码来测试功能,但它没有用(列表元素根本没有显示在生成的html中)。所以我不确定我是否搞砸了javascrit / 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++;            

      }
   }

4 个答案:

答案 0 :(得分:2)

表单中的现有项目使用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 +,则不需要使用AutopopulatingList,任何集合都应该足够了。

答案 1 :(得分: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调用可能是更好的解决方案。

答案 2 :(得分:0)

在以下行中,您在jsp代码中引用i,但我没有定义:

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

定义i的javascript代码在客户端(即浏览器)上执行。在将呈现的html发送到客户端之前,jsp代码在服务器上执行。

答案 3 :(得分:0)

即使该线程较旧并且可以正确回答,也可以为其他初学者提供好处,并解释删除已添加行的逻辑。

让我用最少的代码和带有名字,电子邮件,用户名和性别字段的用户示例进行说明。
考虑到您正在从控制器的usersList中发送3个空用户,这将创建3个空行。现在,您要添加行并将添加的行动态绑定到modelAttribute。

(对于前三行)如果您查看/查看页面源代码,则会看到

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

无论何时提交表单,服务器都不会考虑 id (仅用于帮助客户端验证而添加),但是 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字符串,并用变量名index替换“ 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。
  • 因此在您的控制器中迭代并检查是否为空,然后删除 用户。(使用迭代器不要使用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>

JavaScript必须包含在JSP中

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>';
}