KoolReport's Forum

Official Support Area, Q&As, Discussions, Suggestions and Bug reports.
Forum's Guidelines

Admin Panel - Resources #3248

Closed Frédéric Bégué opened this topic on on Feb 15 - 12 comments

Frédéric Bégué commented on Feb 15

Hi,

Please explain how to create a new record into eg. customers table and getting foreign key id from another table eg. statuses so the query look like this: INSERT INTO customers (code, name, status_id) VALUES ('001', 'Customer Name', 1) but with status_id coming from the statuses table as the statuses.name is showing up when creating a new record (using Select dropdown) but getting an error message as the status_id is missing:

class CustomerResource extends Resource
{
    protected function onCreated()
    {
        $this
            ->manageTable("customers")
            ->inSource(AutoMaker::class);
    }

    protected function query($query)
    {
        return
            $query
                ->join("statuses","customers.status_id","=","statuses.id")
                ->select("customers.code","customers.name", "customers.status_id");

    }

    protected function fields()
    {
        return [
            ID::create("code"),
            Text::create("name"),
            Number::create("status_id")
                ->label("Status")
                ->inputWidget(
                    Select::create()
                        ->dataSource(function(){
                            return AutoMaker::table("statuses")->select("name")->distinct()->orderBy("name");
                        })
                        ->fields(function(){
                            return [
                                Text::create("id")
                            ];
                        })
                ),

        ];
    }
}
Frédéric Bégué commented on Feb 15

Basically is there a way to have a display field and an input value field in inputWidget?

KoolReport commented on Feb 16

Because you only select name on the Select object but use id so id is not found.

Let try this:

                ...
                ->inputWidget(
                    Select::create()
                        ->dataSource(function(){
                            return AutoMaker::table("statuses")->select("id","name")->orderBy("name");
                        })
                        ->fields(function(){
                            return [
                                Number::create("id"),
                                Text::create("name"),
                            ];
                        })
                ),
Frédéric Bégué commented on Feb 16

The formatUsing function got me sorted. Number::create("status_id")

            ->label("Status")
            ->formatUsing(function($value,$row){
                return $row["name"];
            })
            ->inputWidget(
                Select::create()
                    ->dataSource(function(){
                        return AutoMaker::table("statuses")
                            ->select("id","name");
                    })
                    ->fields(function(){
                        return [
                            Number::create("id"),
                            Text::create("name"),
                        ];
                    })
            )

However I noticed a strange behaviour when creating a new record, the status dropdown field is populated with "Active" but I have to manually select it for the record to be created successfully otherwise I get an error message SQL syntax error message as the INSERT INTO query is missing the status_id in VALUES.

KoolReport commented on Feb 16

Please try to set the defaultOption with a value of Active option, in case that there is no value selected yet, it will take the default one.

Select::create()
    ->defaultOption(1); // It should be id value.

Please let us know.

Frédéric Bégué commented on Feb 16

Sorted thank you. Do you have some examples for custom action? Trying to add a soft delete action that updates the deleted_at field to current timestamp. I have been able to add the action to the resource which show up on the list screen. But not sure how to handle this?

In Resource class: protected function actions()

{
    return [
        DetailAction::create(),
        UpdateAction::create(),
        DeleteAction::create(),
        SoftDeleteRecord::create(),
    ];
}

In custom action class:

class SoftDeleteRecord extends Action {

protected function onCreated()
{
    $this->title("My Action")
        ->type("danger")
        ->icon("far fa-trash-alt")
        ->needConfirmation(true)
        ->showOnActionBox(true)
        ->showOnTable(true)
        ->showOnDetail(true);
}

protected function fields()
{
    return [
        ID::create("id"),
        Date::create("deleted_at"),
    ];
}

/**
 * Perform actions
 * @param ActionForm $form Form object that contains all widgets
 * @param DataStore $models Contains list of selected records to be actioned on
 * @return INotification It could be null or an Inoti
 */
protected function handle($form, $models)
{
    //You handle your action here, you have $form result and list of $models
    //in DataStore form.

    //Later you can return a notification like Note, Confirm or Alert
    return Note::success("Action is done!");
}

}

Any example for handle function?

Frédéric Bégué commented on Feb 17

I tried this but getting a syntax error while there is no SQL error on my side:

protected function handle($form, $customers)
    {
        foreach($customers as $customer) {
            $id = $customer["id"];
            $deletedAt = date("Y-m-d H:i:s"); // Current date and time

            return AutoMaker::rawSQL("UPDATE customers SET deleted_at = '".$deletedAt."' WHERE id = {$id}")->run();

            //Later you can return a notification like Note, Confirm or Alert
            //return Note::success("Id: ".$id." deleted at: ".$deletedAt);
        }
    }

The error message:

Message: SQLSTATE[42000]: Syntax error or access violation: 1064 You have an error in your SQL syntax; check the manual that corresponds to your MariaDB server version for the right syntax to use near 'UPDATE customers SET deleted_at = '2024-02-17 07:37:59' WHERE id = 6) as t515...' at line 1

It seems there is an extra parenthese after the id.

Frédéric Bégué commented on Feb 17

On the same note, when creating a new record all fields should be filled otherwise it raise a sql error and the operation failed. Even by using ->allowNullValue(true) do not solve the issue and >defaultOption() is not recognized.

KoolReport commented on Feb 20

Hi,

For the update issue let do this instead:

protected function handle($form, $customers)
    {
            $ids = $customers->pluck("id"); //Get all id need to be deleted in array
            $deletedAt = date("Y-m-d H:i:s"); // Current date and time

            AutoMaker::table("customers")->whereIn("id",$ids)->update(["deleted_at"=>$deletedAt])->run();

            //Later you can return a notification like Note, Confirm or Alert
            //return Note::success("Id: ".$id." deleted at: ".$deletedAt);
    }

The Select has defaultOption and other inputs has defaultValue that you can use to set default value to avoid null.

Frédéric Bégué commented on Feb 20

Thank you the custom action is working like a charm! I updated the function as below to be dynamic:

protected function handle($form, $models)
{
    $ids = $models->pluck("id"); //Get all id need to be deleted in array
    $deletedAt = date("Y-m-d H:i:s"); // Current date and time

    $tableName = $this->resource()->manageTable();
    AutoMaker::table($tableName)->whereIn("id",$ids)->update(["deleted_at"=>$deletedAt])->run();

    //Notification
    return Note::success("Id: ".implode(', ', $ids)." deleted at: ".$deletedAt);
}

Howerver defaultValue raised the following error: Message: Call undefined defaultValue() method. It do not seems to be part of the props Field classes but seems to be only for Input classes. I also tried nullValue and emptyValue as they belong to the Field class but without success.

Is there a way to use Input classes in the fields function in Resource to be able to use defaultValue?

KoolReport commented on Feb 21

Could you please post your full code of your resource. I would like to see.

KoolReport commented on Feb 21

An idea to process the value (check null) before value enter database with processValueToDatabase methods:

...
Text::create("name")
    ->processValueToDatabase(function($value){
        return ($value===null)?"default name":$value;
    },
...

Let us know if it works for you.

Frédéric Bégué commented on Feb 22

Perfect thank you!

Build Your Excellent Data Report

Let KoolReport help you to make great reports. It's free & open-source released under MIT license.

Download KoolReport View demo
help needed
solved

Dashboard