получение элемента списка атрибутов модели Spring с использованием индекса из javascript

Извините, если это было задано где-то еще, но я все осмотрел, нашел несколько ответов, но не полный пример, и я все еще сомневаюсь в этом.

Итак, я добавляю список автозаполнения из моего контроллера 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++;            

      }
   }

person Thomas    schedule 13.11.2012    source источник
comment
увеличение i внутри вашей функции onclick не имеет никакого смысла. каково ваше намерение?   -  person Yevgeniy    schedule 13.11.2012


Ответы (4)


для существующих элементов в вашей форме используйте 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 новую форму «строки» с соответствующими индексами

Например

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

Я думаю, что если вы используете Spring 3 +, вам не нужно использовать AutopopulatingList , любой коллекции должно быть достаточно.

person Josef Procházka    schedule 13.11.2012

Вы неправильно смешиваете JSP EL и Javascript. Вы не можете использовать var i в выражении JSP, т.е. ${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 при загрузке страницы.

person Kevin Bowersox    schedule 13.11.2012
comment
Я немного подчистил код (добавил итерацию i), но в основном я хотел бы добавить новые элементы в список автозаполнения в коде javascript и вернуть список, когда сообщение будет готово. Я не могу использовать jstl внутри javascript, верно? - person Thomas; 13.11.2012
comment
@Thomas: нет, вы не можете, если ожидаете, что ваш код будет выполнен на стороне клиента. - person Yevgeniy; 13.11.2012

в следующей строке вы ссылаетесь на i в своем jsp-коде, но я не определен:

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

код javascript, определяющий i, выполняется на клиенте (т. е. в браузере). JSP-код выполняется на сервере до того, как отрендеренный html отправляется клиенту.

person Yevgeniy    schedule 13.11.2012

Несмотря на то, что этот поток старше и на него дан правильный ответ, в интересах других новичков, а также для объяснения логики для удаления добавленных строк.

Позвольте мне объяснить с помощью минимального кода и примера пользователя с полями firstName, email, userName и gender.
Учитывая, что вы отправляете 3 пустых пользователя в список пользователей из контроллера, это создаст 3 пустых строки. И теперь вы хотите добавить строки и динамически привязать добавленные строки к modelAttribute.

(в случае начальных 3 строк)Если вы проверите/просмотрите исходный код страницы, вы увидите

  • Строки (<input> tags) с разными идентификаторами, например list0.firstName list1.firstName
  • Строки (<input> tags) с разными именами, например list[0].firstName list[1].firstName

Всякий раз, когда форма отправляется, идентификаторы не учитываются сервером (добавляются только для проверки на стороне клиента), но атрибут имени будет интерпретироваться как параметр запроса и использоваться для создания атрибута модели. , поэтому имена атрибутов очень важны при вставке строк.

Добавление строки

Итак, как построить/добавить новые строки?
Если я отправлю 6 пользователей из пользовательского интерфейса, контроллер должен получить 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>. Строки добавляются в пользовательский интерфейс, а также при отправке формы новые добавленные строки будут получены в контроллере.

Удаление строки

Удаление строки немного сложно, я постараюсь объяснить проще

  • Предположим, вы добавили row0, row1, row2, row3, row4, row5
  • Удалил строку 2, строку 3. Не просто скрыть строку, а удалить ее из DOM, перехватив событие.
  • Теперь строки row0, row1, row4, row5 будут отправлены, но в контроллере ваш список пользователей будет иметь 6 пользовательских объектов, но user[2].firstName будет нулевым, а 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>';
}
person PraveenKumar Lalasangi    schedule 05.09.2019