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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/13358950/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-26 18:32:34  来源:igfitidea点击:

getting a spring model attribute list element using an index from javascript

javajavascriptjqueryspringspring-mvc

提问by Thomas

Sorry if this has been asked somewhere else, but I have looked all around, found some answers, but not a complete example and I am still in doubts on this one.

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

So, I am adding an Autopopulating list from my Spring controller to my jsp and I would like to add items on the list inside my javascript/jquery function. Is it possible?

所以,我将一个自动填充列表从我的 Spring 控制器添加到我的 jsp,我想在我的 javascript/jquery 函数中的列表中添加项目。是否可以?

I tried the code below to test the functionality but it did not work (the list elements did not show up at all at the generated html). So Im unsure if Im messing up with the javascrit/spring/jsp syntax or if it is just not possible.

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

Here is the code:

这是代码:

Controller code:

控制器代码:

@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) ;

}

Form code:

表格代码:

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

Criteria code:

标准代码:

public class Criteria{

   String attribute;

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

javascript/jquery code (on the same page as the jsp one):

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++;            

      }
   }

回答by Josef Procházka

for existing items in your form use jstl as

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

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

this will render form like this

这将呈现这样的形式

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

then you simply add with javascript new form "lines" with coresponding indexes

然后您只需添加带有相应索引的 javascript 新表单“行”

for example

例如

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

I think that if you are using spring 3 + you don't need to use AutopopulatingList , Any collection should be enough.

我认为,如果您使用的是 spring 3 +,则不需要使用 AutopopulatingList ,任何集合都应该足够了。

回答by Kevin Bowersox

Your mixing JSP EL and Javascript improperly. You cannot use the var iwithin a JSP expresssion, ie. ${ruleArray[i].operator}. I would recommend using JSTL to iterate through the list and create your attributes within the script.

您不正确地混合 JSP EL 和 Javascript。您不能var i在 JSP 表达式中使用 ,即。${ruleArray[i].operator}. 我建议使用 JSTL 遍历列表并在脚本中创建您的属性。

At this point your script could be setup to just use a string literal 0within the expression. I am assuming you need more robust functionality than this, can you describe it better.

此时,您的脚本可以设置为仅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});           

     }
 }

Using JSTL a solution would look something like:

使用 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>

This solution basically uses JSTL to write Javascript. It may be a better solution to modify your controller to return JSON and just make an Ajax call on page load.

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

回答by Yevgeniy

in the following line you are referencing iin your jsp-code, but i is not defined:

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

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

the javascript code which defines iis executed on the client (i.e. browser). The jsp-code is executed on the server, before the rendered html is sent to the client.

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

回答by PraveenKumar Lalasangi

Even though this thread is older and is answered correctly, For the benefit of others who is beginners and also to explain logic to achieve deletion of added rows.

即使此线程较旧并且回答正确,为了其他初学者的利益,并解释实现删除添加行的逻辑。

Let me explain with a minimal code and User example with firstName, email, userName and genderfields.
Considering you are sending 3 empty users in usersList from controller this will creates 3 empty rows. And now you want to add rows and bind the added rows to modelAttribute dynamically.

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

(in case of initial 3 rows)If you inspect/view page source you will see

(在初始 3 行的情况下)如果您检查/查看页面源代码,您将看到

  • Rows(<input> tags) with different id'slike list0.firstNamelist1.firstName
  • Rows(<input> tags) with different nameslike list[0].firstNamelist[1].firstName
  • <input> tags具有不同id 的Rows( )就像list0.firstNamelist1.firstName
  • Rows( <input> tags) 具有不同的名称,例如list[0].firstNamelist[1].firstName

Whenever form is submitted id'sare not considered by server(added for only for helping client side validations) but name attributewill be interpreted as request parameter and are used to construct your modelAttribute, hence attribute names are very important while inserting rows.

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

Adding row

添加行

So, How to construct/append new rows?
If i submit 6 users from UI, controller should receive 6 user object from usersList. Steps to achieve the same is given below
1. Right click ->view page source. You will see rows like this(you can see *[0].*in first row and *[1].*in second row)

那么,如何构造/追加新行?
如果我从 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. Copy first row and construct a javascript string and replace '0' with variable name index. As given in below sample
  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. Append the constructed row to the <tbody>. Rows get added in UI also on submission of form newly added rows will be received in controller.
  1. 将构造的行附加到<tbody>. 在提交表单时也会在 UI 中添加行,新添加的行将在控制器中接收。

Deleting row

删除行

Deleting row is little bit complicated, i will try to explain in easiest way

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

  • Suppose you added row0, row1, row2, row3, row4, row5
  • Deleted row2, row3. Do not just hide the row but remove it from the DOM by catching event.
  • Now row0,row1,row4,row5 will get submitted but in the controller your userList will have 6 user object but user[2].firstName will be null and user[3].firstName will be null.
  • So in your controller iterate and check for null and remove the user.(Use iterator don't use foreach to remove user object)
  • 假设您添加了 row0、row1、row2、row3、row4、row5
  • 删除了第 2 行、第 3 行。不要只是隐藏行,而是通过捕获事件将其从 DOM 中删除。
  • 现在 row0,row1,row4,row5 将被提交,但在控制器中,您的 userList 将有 6 个用户对象,但 user[2].firstName 将为空,而 user[3].firstName 将为空。
  • 所以在你的控制器中迭代并检查 null 并删除用户。(使用迭代器不要使用 foreach 删除用户对象)

Posting code to benefit beginners.

发布代码以使初学者受益。

//  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
}

In JSP

在 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 needs to be included in JSP

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