K. Maul
K. Maul

Reputation: 23

Populate an html select with spring, thymeleaf, and mongo

I'm trying to populate an HTML select with data from a Mongo collection using Spring and Thymeleaf. I've tried following the advice from these questions: "how do I populate a drop down with a list using thymeleaf and spring", "how to bind an object list with thymeleaf", and "spring app not finding property on object", but I haven't had any luck.

When I use this syntax in my HTML,

<div class="form-group">
        <label for="commoditiesSelect"> Commodities: </label>
        <select multiple="Commodities" id="commoditiesSelect" class="form-control" th:field="*{commodities}">
           <option th:each="commodity : ${possibleCommoditiesList}"
                   th:text="${possibleCommodities}"
                   th:value="${possibleCommodities}"
           />
        </select>
    </div>

I just get a blank list for my select on the webpage. However, I know that the list I send to my model has multiple objects with information in it (via debugging). I've messed around with the syntax, but the closest I've gotten is the pointer to the object displaying on the webpage. Does anyone know where I've gone wrong? Included below are my controller, service implementation, PossibleCommodities class, and PossibleCommoditiesRepository class.

Controller:

@GetMapping("/welcomeMatForm")
public String welcomeMatForm(Model model) {
    List<PossibleCommodities> possibleCommoditiesList = welcomeMatService.getPossibleCommodities();
    model.addAttribute("possibleCommoditiesList", possibleCommoditiesList);
    model.addAttribute("welcomeMatForm", new WelcomeMatForm());
    return "welcomeMatForm";
}

Service Implementation class:

    public List<PossibleCommodities> getPossibleCommodities(){
    List<PossibleCommodities> listOfCommodities = possibleCommoditiesRepository.findAll();
    return listOfCommodities;
}

PossibleCommodities class:

package com.sensus.analytics.welcomemat.core.model;

import org.springframework.data.annotation.TypeAlias;
import org.springframework.data.mongodb.core.mapping.Document;

@Document(collection = "possible_commodities")
@TypeAlias("PossibleCommodities")
public class PossibleCommodities extends BasicMongoDocument{

public String commodityName;
private int commodityId;

public String getCommodityName(int commodityId) {
    return commodityName;
}

public void setCommodityName(String commodityName) {
    this.commodityName = commodityName;
}

public int getCommodityId(String commodityName){
    return commodityId;
}

public void setCommodityId(int commodityId) {
    this.commodityId = commodityId;
}
}

PossibleCommoditiesRepository class:

package com.sensus.analytics.welcomemat.core.repository;

import com.sensus.analytics.welcomemat.core.model.PossibleCommodities;
import org.springframework.data.mongodb.repository.MongoRepository;
import java.util.List;

public interface PossibleCommoditiesRepository extends MongoRepository<PossibleCommodities, String>  {
public List<PossibleCommodities> findAll();
}

EDIT: I've tried this common syntax for the HTML as well:

<div class="form-group">
        <label for="commoditiesSelect"> Commodities: </label>
        <select multiple="Commodities" id="commoditiesSelect" class="form-control" th:field="*{commodities}">
           <option th:each="commodity : ${possibleCommoditiesList}"
                   th:text="${possibleCommodities.commodityName}"
                   th:value="${possibleCommodities.commodityName}"
           />

        </select>
    </div>

but it gives me this error: EL1007E:(pos 0): Property or field 'commodityName' cannot be found on null

Upvotes: 2

Views: 1499

Answers (1)

Metroids
Metroids

Reputation: 20487

In a line like this, you have to know where the variables are being defined:

<option th:each="commodity : ${possibleCommoditiesList}" th:text="${possibleCommodities}" th:value="${possibleCommodities}" />

You have 3 variables here

  • commodity -- defined by the th:each expression
  • possibleCommoditiesList - defined by adding it to the model (in your controller)
  • possibleCommodities - not defined anywhere. This resolves to null, and so you get a list of blank options. In the case of your second example, the error is caused by thymleaf attempting to call getCommodityName() on a null object.

Since in your th:each, you designated the variable as commodity, you probably need to do something like this:

<option th:each="commodity : ${possibleCommoditiesList}" th:text="${commodity.commodityName}" th:value="${commodity.commodityName}" />

Upvotes: 1

Related Questions