Livewire model binding for casted model attributes - model-binding

I have custom cast in the Laravel model:
protected $casts = [
'price' => CustomCast::class,
];
The casted property is an object and thus used in various ways across the application by calling its public methods:
$price->getAmount();
$price->convert();
If I bind to this model with Livewire the value understandably is not displayed as it requires a method call. The following bind displays [object Object]
<input wire:model="tx.price" />
I tried below to no avail:
<input wire:model="tx.price" value={{ $tx->price->getAmount() }} />
Is it possible to work around this with Livewire?

Related

Can't we link a grails form to a bean

As in Struts n JSF, we link a form to a bean(eg. backing bean in JSF).
But in grails, we are using params to set values of the bean. Is there any other way to automatically map a form to the bean?
Grails has the possibility to auto bind values from the params map to a given domain instance / command object. This can be achieved by defining the correct beans as a parameter for your controller methods. Take this example:
Controller:
class AuthorController {
def save(Author author) {
// matching param values are bound to the author instance
assert params.name == "myName"
assert author.name == "myName"
}
}
gsp with form:
<g:form controller="author" action="save">
<g:field name="name" value="myName" />
<g:submitButton name="save" value="Save" />
</g:form>
Sometimes is better to use the Command Objects provided by Grails, the domain class can be wrapped only matching the name of the form fields with the attributes names of the class.
But Command Objects can provide an intermediate layer of validation and abstraction to generate the model bean.
http://grails.org/doc/2.3.0/guide/single.html#commandObjects

How to use Grails bindData when using collections in entity fields and properties

I have the following domain classes:
Airport:
class Airport {
String airportName
List<Flight> flights
static hasMany = [flights: Flight]
static mappedBy = [flights: "departureAirport"]
}
Flight:
class Flight {
String flightName
Integer numOfStaff
Airport departureAirport
}
I have in a form the following input fields which is correctly prints the saved airport and it's flights:
<input name="airportName" value="${airportInstance.airportName}" />
<input name="id" value="${airportInstance.id}" />
<input name="version" value="${airportInstance.version}" />
<g:set var="counter" value="${0}" />
<g:each in="${airportInstance?.flights?}" var="f">
<div>
name : <input name="flights[${counter}].flightName" value="${f.flightName}" />
id : <input name="flights[${counter}].id" value="${f.id}" />
numOfStaff : <input name="flights[${counter}].numOfStaff" value="${f.numOfStaff}" />
<g:set var="counter" value="${counter + 1}" />
</div>
</g:each>
I post the form to the following controller action:
#Transactional
def update() {
Airport airportInstance = Airport.get(params.id)
// doesn't work as well
// airportInstance.properties = params
bindData(airportInstance, params)
airportInstance.save flush:true
request.withFormat {
form multipartForm {
flash.message = message(
code: 'default.updated.message',
args: [
message(
code: 'Airport.label',
default: 'Airport'
),
airportInstance.id
]
)
redirect airportInstance
}
'*'{ respond airportInstance, [status: OK] }
}
}
When I modify airportName or some of the flights properties (e.g.: numOfStaff) and I click update (post it to the controller action), Grails does his work correctly and updates my changes.
But if I manually add a new instance in the view e.g.: if there were two flights flights[0] and flights[1] listed by g:each and I add flights[2] it doesn't create a new instance of Flight and doesn't save it.
The same if I try to delete an existing flight from the view and post it to the controllers update action.
I'm using grails version 2.3.9
My questions are:
Am I doing something wrong?
Is it a Grails bug or Grails developers implemented bindData method like this for some reason?
What is the best way in Grails to implement issue like above (I mean giving the name attributes like foo[index].prop where foo is a collection in the entity).
Sorry for the junk html.
Thank you guys, for the answers.
I found the solution. If I declare a controller action like:
def update(Airport airport) {
// ...
}
In this case before the controller action is executed Grails will automatically create an instance of the Airport class and populate its properties by binding the request parameters.
If there is an id request parameter then instead of invoking the domain class constructor to create a new instance a call will be made to the static get method on the domain class and the value of the id parameter will be passed as an argument. Whatever is returned from that call to get is what will be passed into the controller action. This means that if there is an id request parameter and no corresponding record is found in the database then the value of the command object will be null.
See Grails Reference Documentation: http://grails.org/doc/latest/guide/theWebLayer.html#commandObjects

Hiddenfor not getting correct value from view model

I have a multi-step file import process. I have a hidden form input in my view that I am trying to populate with the "CurrentStep" from the view model.
<% = Html.HiddenFor(model => model.CurrentStep) %>
CurrentStep is an Enum and I always get the default value rather than the one I provided to the view model. on the other hand this gets me the correct value:
<p><% = Model.CurrentStep %></p>
I realise I could just hand code the hidden input but I want to know: what am I doing wrong? Is there a better way to keep track of the current step between POSTs?
What you are doing wrong is that you are trying to modify the value of a POSTed variable in your controller action. So I suppose you are trying to do this:
[HttpPost]
public ActionResult Foo(SomeModel model)
{
model.CurrentStep = Steps.SomeNewValue;
return View(model);
}
and html helpers such as HiddenFor will always first use the POSTed value and after that the value in the model.
So you have a couple of possibilities:
Remove the value from the modelstate:
[HttpPost]
public ActionResult Foo(SomeModel model)
{
ModelState.Remove("CurrentStep");
model.CurrentStep = Steps.SomeNewValue;
return View(model);
}
Manually generate the hidden field
<input type="hidden" name="NextStep" value="<%= Model.CurrentStep %>" />
Write a custom helper which will use the value of your model and not the one that's being POSTed
My solution was to use Darin's second option, because option 1 (clearing from the model state) means hard coding a string (and the naming convention can be tricky with complex models), and wanted to avoid option 3 because I already have so many custom helpers.
<input type="hidden" name="#Html.NameFor(x => Model.SomeId)" value="#Model.SomeId" />
Just a reminder that you can use Html.NameFor to keep things clean.
Make sure you model property has a "set" operator.
This won't get updated on post-back:
#Html.HiddenFor( m => m.NoSeq)
public Class MyModel
{
int _NoSeq;
public NoSeq
{
get { return _NoSeq };
}
}

asp.net mvc and valid xhtml?

For some reason an html helper is outputting this html which doesnt validate.
the validator tells me
There is no attribute "Length"
<%= Html.CheckBox("Medicamentos", Model.Medicamentos) %>
is outputting
<input type="checkbox" value="true" name="Medicamentos" id="Medicamentos" checked="checked" length="4">
I assume that it's matching the signature that takes a string and an object since I don't know what Model.Medicamentos is. In that case it takes the properties of the object and turns them into attributes on the element. I suspect that you simply want to use the Checked attribute on the Model property specified as the default value of the checkbox, i.e.,
<%= Html.CheckBox( "Medicamentos", Model.Medicamentos.Checked ) %>
In, which case, assuming that Checked is boolean it will match the correct method signature on the helper extension.

Grails form data binding when another domain object is referenced in the form

How do I get Grails data binding to correctly bind referenced objects (such as Country in the example below)?
Given the following two Grails domain classes ..
class User {
String username
Country country
}
class Country {
String name
}
.. and the following HTML form ..
<g:form>
<g:textField name="user.username" value="${user.username}" />
<g:select name="user.country" from="${Country.list()}" optionKey="id" />
</g:form>
.. and the following code in the corresponding action ..
User user = new User(params["user"])
.. I would have hoped that user.username and user.country would get bind. However, it appears as if username.username gets bind, whereas user.country is not. What is the correct syntax to bind referenced objects (user.country in this example)?
The binding of the "country" property starts working if ..
<g:select name="user.country" from="${Country.list()}" optionKey="id" />
.. is changed to ..
<g:select name="user.country.id" from="${Country.list()}" optionKey="id" />
You should also look into command objects. They can validate and bind all of your parameters at once.

Resources