如何在百里香选择选项中获取对象?
Posted
技术标签:
【中文标题】如何在百里香选择选项中获取对象?【英文标题】:How can get the object in thymeleaf select option? 【发布时间】:2018-03-19 15:04:19 【问题描述】:在自动完成中,我得到了预期的产品名称。
我想根据所选产品进行一些计算。但在 doCalculation 函数中,我得到的是id
而不是“价格”。所以计算没有按预期工作。
假设如果我更改 String idExpression = "#price";
然后计算按预期工作但订单未保存。由于出现如下错误
Failed to convert property value of type [java.lang.String] to required type [com.myapp.domain.Product] for property product; nested exception is
org.springframework.core.convert.ConversionFailedException: Failed to convert from type [java.lang.String] to type [@javax.persistence.OneToOne
@io.springlets.format.EntityFormat com.myapp.domain.Product] for value 2500; nested exception is java.lang.IllegalStateException: Parsers are not allowed to return null: io.springlets.format.EntityParser@2201ba1c
所以我想在保存功能不应该被破坏的同时得到计算价格。现在第一个或第二个对我有用。
ProductsCollectionThymeleafController.java
@GetMapping(produces = MediaType.APPLICATION_JSON_VALUE, name = "select2", value = "/s2")
@ResponseBody
public ResponseEntity<Select2DataSupport<Product>> select2(GlobalSearch search, Pageable pageable,
Locale locale)
Page<Product> products = getProductService().findAll(search, pageable);
String idExpression = "#id";
Select2DataSupport<Product> select2Data =
new Select2DataWithConversion<Product>(products, idExpression, getConversionService());
return ResponseEntity.ok(select2Data);
OrderCollectionThymeleafController.java
@PostMapping(name = "create")
public ModelAndView create(@Valid @ModelAttribute Order order, BindingResult result,
Model model)
if (result.hasErrors())
populateForm(model);
return new ModelAndView("/order/create");
Order newOrder = getOrderService().save(order);
UriComponents showURI = getItemLink().to(OrderItemThymeleafLinkFactory.SHOW)
.with("order", newOrder.getId()).toUri();
return new ModelAndView("redirect:" + showURI.toUriString());
orderview.html
<form class="form-horizontal validate" method="POST" data-th-object="$order" data-th-action="@$collectionLink.to('create').with('order', order.id)">
<fieldset id="containerFields">
<div class="form-group has-error has-feedback" data-z="3c00987d" id="servicio-product-field" data-th-classappend="$#fields.hasErrors('product')? 'has-error has-feedback'" data-th-class="form-group" data-th-with="collectionLink=$@linkBuilder.of('ProductsCollectionThymeleafController')">
<label for="product" class="col-md-3 control-label" data-th-text="#label_servicio_product">Product</label>
<div class="col-md-6">
<!-- Select2 -->
<select data-th-field="*product" onChange="doCalculation()" class="form-control dropdown-select-ajax" data-allow-clear="true" data-data-ajax--url="$collectionLink.to('select2')" data-ajax--cache="true" data-ajax--delay="250" data-ajax--data-type="json" data-data-placeholder="#info_select_an_option">
<option data-th-unless="*product == null" data-th-value="*product.id" data-th-text="*product" selected="selected">Product</option>
</select>
<span data-th-classappend="$#fields.hasErrors('product')? 'glyphicon glyphicon-remove form-control-feedback'" class="glyphicon glyphicon-remove form-control-feedback" data-th-if="$#fields.hasErrors('product')" aria-hidden="true"></span>
<span id="product-error" class="help-block" data-th-if="$#fields.hasErrors('product')" data-th-errors="*product">Error message.</span>
</div>
</div>
<script>
function doCalculation()
var price = document.getElementById("product").value;
alert("price: " + price);
// Do some calculation
doCalculation();
</script>
</fieldset>
</form>
Product.java
@RooJavaBean
@RooToString
@RooJpaEntity
@RooEquals(isJpaEntity = true)
@Entity
@EntityFormat
public class Product
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
private String productName;
@Min(1L)
@NumberFormat
private Integer price;
@OneToOne(fetch = FetchType.LAZY)
@EntityFormat
private Order order;
public static final String ITERABLE_TO_ADD_CANT_BE_NULL_MESSAGE = "The given Iterable of items to add can't be null!";
public static final String ITERABLE_TO_REMOVE_CANT_BE_NULL_MESSAGE = "The given Iterable of items to add can't be null!";
public Long getId()
return this.id;
public void setId(Long id)
this.id = id;
public Integer getPrice()
return this.price;
public void setPrice(Integer price)
this.price = price;
public String getProductName()
return this.productName;
public void setProductName(String productName)
this.productName = productName;
public Order getOrder()
return this.order;
public void setOrder(Order order)
this.order= order;
Order.java
@RooJavaBean
@RooToString
@RooJpaEntity
@RooEquals(isJpaEntity = true)
@Entity
@EntityFormat
public class Order
@Id
@GeneratedValue(strategy = GenerationType.AUTO)
private Long id;
@Version
private Integer version;
@OneToOne(cascade = javax.persistence.CascadeType.MERGE,
javax.persistence.CascadeType.PERSIST , fetch = FetchType.LAZY, mappedBy = "order")
@RooJpaRelation(type = JpaRelationType.AGGREGATION)
@EntityFormat
private Product product;
public static final String ITERABLE_TO_ADD_CANT_BE_NULL_MESSAGE = "The given Iterable of items to add can't be null!";
public static final String ITERABLE_TO_REMOVE_CANT_BE_NULL_MESSAGE = "The given Iterable of items to add can't be null!";
/**
* This `equals` implementation is specific for JPA entities and uses the
* entity identifier for it, following the article in
* https://vladmihalcea.com/2016/06/06/how-to-implement-equals-and-hashcode-using-the-jpa-entity-identifier/
*
* @param obj
* @return Boolean
*/
public boolean equals(Object obj)
if (this == obj)
return true;
// instanceof is false if the instance is null
if (!(obj instanceof Order))
return false;
return getId() != null && Objects.equals(getId(), ((Order) obj).getId());
/**
* This `hashCode` implementation is specific for JPA entities and uses a
* fixed `int` value to be able to identify the entity in collections after
* a new id is assigned to the entity, following the article in
* https://vladmihalcea.com/2016/06/06/how-to-implement-equals-and-hashcode-using-the-jpa-entity-identifier/
*
* @return Integer
*/
public int hashCode()
return 31;
public Long getId()
return this.id;
public void setId(Long id)
this.id = id;
public Integer getVersion()
return this.version;
public void setVersion(Integer version)
this.version = version;
public Product getProduct()
return this.product;
public void setProduct(Product product)
this.product = product;
public void addToProduct(Product product)
if (product == null)
removeFromProduct();
else
this.product = product;
product.setOrder(this);
public void removeFromProduct()
if (this.product != null)
product.setOrder(null);
this.product = null;
【问题讨论】:
【参考方案1】:默认情况下,Select2DataWithConversion
数据类型仅返回将设置为 value
属性的标识符 option
元素和对象的表示形式(在您的情况下为产品名称)为 text
option
元素的属性。
这是 select2 组件需要构建的最少信息。
https://select2.org/data-sources/formats
但是,正如您在回答中所述,在 Select2 组件中需要更多信息确实很常见。为此,我们重载了Select2DataWithConversion
的构造函数,包括一个布尔参数来返回对象的全部信息。
在这里检查这个重载的构造函数:
https://github.com/DISID/springlets/blob/master/springlets-data/springlets-data-commons/src/main/java/io/springlets/data/web/select2/Select2DataWithConversion.java#L76
因此,您只需更改您的 ProductsCollectionThymeleafController.java 以使用它:
Select2DataSupport<Product> select2Data = new Select2DataWithConversion<Product>(products, idExpression, getConversionService(), true);
既然您的 select2 组件将接收额外信息,您需要在创建选项时将其存储在您的 select2 选项的 data-*
属性中。为此,请使用提供 select2 组件的 templateSelection
函数。
https://select2.org/programmatic-control/retrieving-selections#using-a-jquery-selector
现在,您的 doCalculation
应该获得选定的选项,然后是 data-price
属性。
<script>
function doCalculation()
var price = $('#product').find(':selected').data('price');
alert("price: " + price);
//Do some calculation
doCalculation();
</script>
仅此而已!
编辑:我刚刚创建了以下项目,您可以在其中找到所需的行为:https://github.com/jcagarcia/proofs/tree/master/select2-with-extra-info 只需检查以下提交中的必要更改:https://github.com/jcagarcia/proofs/commit/105c18f7ad0da4d1e2089fbf71d4f27ccdb60689
希望对你有帮助,
【讨论】:
获取未定义的价格价值 因为在这个 $('#accomidation').find(':selected') 中找不到数据。添加了 console.log(price);并找到了这个 你是如何实现templateSelection
select2函数的?
我刚刚使用 Spring Roo 创建了一个示例项目,您可以在其中找到解决方案。 github.com/jcagarcia/proofs/tree/master/select2-with-extra-info 只需检查我已应用必要更改的提交即可。 github.com/jcagarcia/proofs/commit/…以上是关于如何在百里香选择选项中获取对象?的主要内容,如果未能解决你的问题,请参考以下文章