Laravel DataTables move to domain class - laravel

I've managed to correctly set up a Laravel DataTable with the following code in a controller method.
// Retrieve (potentially filtered) data
$users = User::with("role", "language", "country")->select([
"support_code", "first_name", "last_name", "subscription_expires",
"email_address", "user_name", "location",
"role_id", "language_id", "country_id"
]);
// Return data as JSON
return Datatables::of($users)->make(true);
However, I now wish to move this code out of the controller and into a domain object/separate class. The problem is that this doesn't work as the DataTables JS sends a long query string via its Ajax method, and this isn't being passed along to the domain class.
I have two questions. First, how do I send this query string to the domain class? Second, how do I offer it up to the Datatables::of($users) -> make(true) method?

Lol. My fault. I forgot to include use Yajra\Datatables\Datatables;
Because it was an Ajax request, I didn't get the namespace error message.

Related

Creating Laravel DTO from request with optional fields

I'm using Spatie Laravel-data to create data objects to pass in and out of an API. I'm hitting an issue trying to create a DTO from a POST request - there are certain fields that won't be passed in for an INSERT, the obvious one being ID.
I'm failing validation each time, with the following error
{
"message": "The given data was invalid.",
"errors": {
"id": [
"The id field is required."
]
}
}
My DTO class follows these instructions and looks like this:
class MemberData extends Data
{
public function __construct(
public int|Optional $id,
#[Max(255)]
public string $first_name,
#[Max(255)]
public string $last_name,
)
{}
}
How can I get past validation without providing an ID? Or should I be creating a different DTO for an INSERT?
Problem solved. If I had listened to the complaints from my IDE, I would have realised that Optional is a class that needs to be included.
Same goes for the attribute validation (Max)
Adding this to the top of the data object fixed the issue.
use Spatie\LaravelData\Optional;
use Spatie\LaravelData\Attributes\Validation\Max;

Laravel, related model reuturened names

I have a model that has a related model
class A extends Model{
public function niceName()
{
return this->hasOne('App\NiceName2' ...);
}
In the controller when I retrieve data with submodel the result is like
a[nice_name_2] (using the table name) and I would like it to be a[NiceName2].
Is there a way to have an alias for the returned result? In cakePHP i know there is propertyName to set this on relations. Laravel has a similar feature?
Thanks
Laravel uses the convention of camelCase for method names and snake_case for attributes. I'm not sure there's an easy way around this.
When Laravel serializes the data, it converts relationships to snake_case, by convention. So NiceName2 would become nice_name2 when you execute toArray() or when the model is serialized (either in a JSON response or otherwise).
How this works is:
When you access $model->nice_name2 it converts the property name back to niceName2 to check for a relationship method with that name. When serializing, it converts the relationship niceName2 to the attribute name nice_name2.

Grails command object validation with Ajax

In a Grails project I have a command object to validate submitted forms. This command obj. also has custom validators. The data is submitted with jQuery ajax ($.post).
My question is how can I now map the data send with jQuery Ajax to the properties listed in the Command object?
For example:
$.post('comment/save', {id: id, title: title});
and then in the controller:
def save(saveCommand cmd){
if (!cmd.validate()){
...
}
}
class saveCommand {
Comment comment_id // maps to: params.comment_id send with ajax
String title // maps to: params.title send with ajax
// constraints
// validators
}
The comment_id attribute should be bound from a "comment_id" parameter in the parameter map you sent from jQuery, not as "id" as you have right now.
Anyway, I guess you have a Comment domain class, and you expect to bind this entity from database. In this case, you should add a ".id" suffix to your parameter name.
$.post('comment/save', {"comment_id.id": id, "title": title});
PS: maybe you want to rename the "comment_id" to "comment" in your command class. Doing that, you will have to change the parameter name in your ajax request as "comment.id".

Enum unbinds from the model on ajax call

I am reading an enum value from the db then bind it to the model. When i post the form with ajax, somehow the enum is unbound or the model property in null or zero but it display properly on the view. I have posted code below. Im using entityframework and mvc3
//model code constructor
public CarModel(Car car)
{
State=(CarState)car.State;
//car.State comes in as an int
//etc setting other variables
}
//CarState property
public CarState {get;set;}
//model code
#Html.DisplayFor(m=>m.CarState)
//Controller code()
Save(CarModel car)
{
//I have code that saves the changes
}
The minute i get to "car", CarState has no value.
It's not quite clear how you are passing this value to the controller action. You have only shown some #Html.DisplayFor(m=>m.CarState) but obviously this only displays a label in the view. It doesn't send anything back to the server. If you want to send some value back you will have to use an input field inside the form.
For example:
#Html.EditorFor(m => m.CarState)
or use a HiddenFor field if you don't want the user to edit it.
In any case you need to send that value to the server if you expect the model binder to be able to retrieve it. The model binder is not a magician. He cannot invent values. He binds values to your model from the Request.

Setup knockoutJS view model to bind to one-to-many property

I have a controller in grails that I am sending an ajax JSON post to with a knockoutJS view model. The view model (along with a javascript object) looks like this:
var childProperty= function(name, id) {
this.name = name;
this.id = id;
};
//KnockoutJS - Main view model
var viewModel = {
id: ko.observable(1),
childProperty: ko.observable(new childProperty("Chuck",1))
}
The data model on the controller side is trying to automatically use the Spring binding magic and bind the JSON request parameters to a new instance of my data model like so:
def jUpdate = {
def update = new SomeObject(params)
}
The problem comes in when I want the Spring binding to detect that childProperty.id is a one-to-many relationship in the data model and to go fetch the related property in the data model. The Grails documentation says this:
Data binding and Associations
If you have a one-to-one or many-to-one association you can use
Grails' data binding capability to update these relationships too. For
example if you have an incoming request such as:
/book/save?author.id=20
Grails will automatically detect the .id
suffix on the request parameter and look-up the Author instance for
the given id when doing data binding such as:
def b = new Book(params)
I am using the ko.toJS utility function and the simple properties are binding correctly. How can I set the view model child property up so that when it is posted to the grails controller, Spring detects it properly and fetches the associated record and builds the object?
I was never able to get the automagic spring bindings to work, so I just passed over the id for the child objects and manually set them on the server side in the params map. After that, GORM fetches the record appropriately. Something like this:
def update = {
params.put("childObject.id",params.childObjectId)
params.remove("childObjectId")
def parentObject = new ParentObject(params)
}
This fetches the related items and builds the object. If you had a lot of related fields, this would become a painful process.

Resources