newbie to grails
newbie to grails

Reputation: 42

Type Mismatch Error using g:select with a domain object

I am developing a simple app using grails that records loans. And there are three simple domain classes:

  1. CompanyCategory - basically two types of category, "Bank" & "Others"
  2. Company - all the companies that are in the system.
  3. Loan - records which bank we borrow from, and how much.

The following are the simple domain classes:

class CompanyCategory {

    String  categoryName

}

class Company {

    String              companyName
    CompanyCategory     category

}

class Loan {

    Company     bank
    BigDecimal  loanAmount

}

From my controller, I have found all the companies that are of bank type, and pass it to my gsp, as such:

def create() {

    // Looking for all the companies that are of Bank category
    def banks = Company.findAllByCategory( CompanyCategory.findAllByCategoryName("Bank") )

    respond new Loan(params), model:[banks: banks]
}

In my GSP, this is how it looks like:

        <g:form resource="${this.loan}" method="POST">


            <fieldset class="form">

                <f:field bean="loan" property="bank" >
                    <g:select name="lender" from="${banks}" value="{banks?.id}" />
                </f:field>

                <f:field bean="loan" property="loanAmount" />

            </fieldset>


            <fieldset class="buttons">
                <g:submitButton name="create" class="save" value="${message(code: 'default.button.create.label', default: 'Create')}" />
            </fieldset>
        </g:form>

Up to here, we can see from the dropdown list that only the Banks are shown in the dropdown list, and the rest of the companies are not.

However, when I try to submit the form, I get the following error:

Property [bank] of class [class test.Loan] cannot be null

What did I do wrong? Or is there a better way to do this?

Thanks in advance.

EDIT 1

This is the save method

@Transactional
def save(Loan loan) {
    if (loan == null) {
        transactionStatus.setRollbackOnly()
        notFound()
        return
    }

    if (loan.hasErrors()) {
        transactionStatus.setRollbackOnly()
        respond loan.errors, view:'create'
        return
    }

    loan.save flush:true

    request.withFormat {
        form multipartForm {
            flash.message = message(code: 'default.created.message', args: [message(code: 'loan.label', default: 'Loan'), loan.id])
            redirect loan
        }
        '*' { respond loan, [status: CREATED] }
    }
}

EDIT 2 After changing the code to:

                <f:field bean="loan" property="bank" >
                    <g:select name="bank" from="${banks}" value="{banks?.id}" />
                </f:field>

The NULL pointer has been fixed, but I now got a type mismatched error. Anyone know how do i fix this?

Thanks in advance.

Upvotes: 0

Views: 736

Answers (2)

bassmartin
bassmartin

Reputation: 525

You need to bind the selected "bank id" to "bank.id" via the name attribute, use optionKey option and fix the value options :

<f:field bean="loan" property="bank" >
    <g:select class="form-control" id="bank" name="bank.id" from="${banks}" optionKey="id" optionValue="companyName" value="${loan.bank.id}"/>
</f:field>

Upvotes: 1

elixir
elixir

Reputation: 1442

Change

<f:field bean="loan" property="bank" >
    <g:select name="lender" from="${banks}" value="{banks?.id}" />
</f:field>

to this

<f:field bean="loan" property="bank" >
    <g:select name="bank" from="${banks}" optionValue="companyName" optionKey="id" noSelection="['': '']" />
</f:field>

When you submit the form, Grails uses the "name" property to bind data to domain objects.

To fix type mismatch error

<f:field bean="loan" property="loanAmount" name="loanAmount"/>

Hope that helps.

Upvotes: 1

Related Questions