Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Detail view and compatibility with Flexible Content #102

Open
dividy opened this issue Dec 17, 2019 · 24 comments
Open

Detail view and compatibility with Flexible Content #102

dividy opened this issue Dec 17, 2019 · 24 comments
Labels
compatibility Compatibility in combination with other packages

Comments

@dividy
Copy link

dividy commented Dec 17, 2019

Hello,

I'm using Nova Dependency Container inside Flexible Content.

Any of you using these 2 together successfully ?

I'm having 2 issues :

Problem 1 - If I add 2 products to my "product" layout, values are saved correctly in DB but on the edit form, the products's fields have the last product's values (eg. in DB: sale_price: 1 / sale_price: 3 gives sale_price: 3 / sale_price: 3 in the edit form).

Problem 2 - It won't show dependent fields on the detail view when values are matched...

Any idea ?

@wize-wiz
Copy link
Contributor

@dividy I need a working setup on how you use both packages.

The dependency container still has some minor problems when used within a flexible content layout. The overall problem of the dependency container not behaving correctly on index/detail/etc is already known and I'm currently working out some solutions.

@wize-wiz wize-wiz added the compatibility Compatibility in combination with other packages label Dec 17, 2019
@dividy
Copy link
Author

dividy commented Dec 17, 2019

Hello @wize-wiz !

I use this Flexible Content preset :

<?php
namespace App\Nova\Flexible\Presets;

use Whitecube\NovaFlexibleContent\Flexible;
use Whitecube\NovaFlexibleContent\Layouts\Preset;
use Laravel\Nova\Fields\ID;
use Laravel\Nova\Fields\Text;
use Laravel\Nova\Fields\Textarea;
use Laravel\Nova\Fields\Number;
use Laravel\Nova\Fields\Image;
use Laravel\Nova\Fields\Markdown;
use Laravel\Nova\Http\Requests\NovaRequest;
use Laravel\Nova\Fields\HasMany;
use Laravel\Nova\Fields\BelongsTo;
use Laravel\Nova\Fields\Select;
use Titasgailius\SearchRelations\SearchesRelations;
use Laravel\Nova\Fields\Status;
use Laravel\Nova\Fields\Badge;
use Sloveniangooner\SearchableSelect\SearchableSelect;
use Epartment\NovaDependencyContainer\HasDependencies;
use Epartment\NovaDependencyContainer\NovaDependencyContainer;
use Illuminate\Support\Facades\Route;

class ProductPreset extends Preset
{
    use HasDependencies;

    /**
     * Create a new preset instance
     *
     * @return void
     */
    public function __construct()
    {
    }

    /**
     * Execute the preset configuration
     *
     * @return void
     */
    public function handle(Flexible $field)
    {
        $field->button('Ajouter un produit');
        $field->confirmRemove($label = 'Confirmez la suppression du produit : ', $yes = 'Supprimer', $no = 'Annuler');
        $field->hideFromIndex();
        
        $fields = [
            Select::make('Type de contrat', 'type')->options([
                'L' => 'Location',
                'R' => 'Relevé',
                'V' => 'Vente',
                'VU' => 'Vente unique',
                'VL' => 'Vente & Location',
            ])->displayUsingLabels()->rules('required'),

            NovaDependencyContainer::make([ Text::make('Prix en Location (htva)', 'price_rent') ])->dependsOn('type', 'L'),
            NovaDependencyContainer::make([ Text::make('Prix en Location (htva)', 'price_rent') ])->dependsOn('type', 'VL'),
            NovaDependencyContainer::make([ Text::make('Prix de Vente (htva)', 'price_sale') ])->dependsOn('type', 'V'),
            NovaDependencyContainer::make([ Text::make('Prix de Vente (htva)', 'price_sale') ])->dependsOn('type', 'VU'),
            NovaDependencyContainer::make([ Text::make('Prix de Vente (htva)', 'price_sale') ])->dependsOn('type', 'VL'),
            NovaDependencyContainer::make([ Text::make('Prix du Relevé (htva)', 'price_reading') ])->dependsOn('type', 'R'),

        ];

        $field->addLayout('Produit', 'product', $fields);

    }
}

@wize-wiz
Copy link
Contributor

wize-wiz commented Dec 17, 2019

@dividy This is a general problem. What you are basically doing is declaring multiple fields with the same name. All fields have to be present though.

But from what I can read from your code, maybe this is what you try to accomplish?

    public function handle(Flexible $field)
    {
        $field->button('Ajouter un produit');
        $field->confirmRemove($label = 'Confirmez la suppression du produit : ', $yes = 'Supprimer', $no = 'Annuler');
        $field->hideFromIndex();
        
        $fields = [
            Select::make('Type de contrat', 'type')->options([
                'L' => 'Location',
                'R' => 'Relevé',
                'V' => 'Vente',
                'VU' => 'Vente unique',
                'VL' => 'Vente & Location',
            ])->displayUsingLabels()->rules('required'),

            NovaDependencyContainer::make([ Text::make('Prix en Location (htva)', 'price_rent') ])
                ->dependsOn('type', 'VL')
                ->dependsOn('type', 'L'),
            NovaDependencyContainer::make([ Text::make('Prix de Vente (htva)', 'price_sale') ])
                ->dependsOn('type', 'V')
                ->dependsOn('type', 'VU')
                ->dependsOn('type', 'VL'),
            NovaDependencyContainer::make([ Text::make('Prix du Relevé (htva)', 'price_reading') ])  
                ->dependsOn('type', 'R'),
        ];

        $field->addLayout('Produit', 'product', $fields);
    }

Chaining dependsOn always result in an or statement.

@dividy
Copy link
Author

dividy commented Dec 18, 2019

Yes that's intended.
If you select 'L' or 'VL', I want the input field 'Prix en Location' to be displayed.
If you select 'R' I want the input field 'Relevé' to be displayed.
If you select 'V' or 'VU' or 'VL', I want the input field 'Prix de Vente' to be displayed.

I noticed the dependent input fields id are called "price_rent", "price_sale" and "price_reading" instead of eg. "02d76404b3373b65__price_rent" is it intended ?

Do you have any idea why saving is OK but editing shows the value of the last item ?

@dividy
Copy link
Author

dividy commented Dec 23, 2019

Any idea @wize-wiz ? :)

@wize-wiz
Copy link
Contributor

@dividy I have to rebuild the setup your using and try to understand the problem. This won't happen until the first week of the new year.

Happy holiday :)

@dividy
Copy link
Author

dividy commented Jan 2, 2020

Would be great because I can't deliver my app to the customer next week without this.

@dividy
Copy link
Author

dividy commented Jan 6, 2020

Hi @wize-wiz, happy new year !

Any chance for an update in the next days ?

@bernhardh
Copy link

bernhardh commented Jan 7, 2020

Same here. I have a similar problem, with an easier setup:

public function fields(Request $request)
{
    return [
        ID::make()->sortable(),
        Flexible::make("Data")
            ->addLayout("Simple Layout", "html", [
                Select::make("Type", "type")->options([
                    "html" => "HTML",
                    "plain" => "Plaintext"
                ]),
                NovaDependencyContainer::make([
                    Trix::make('Content', 'html_content')
                ])->dependsOn('type', "html"),
                NovaDependencyContainer::make([
                    Textarea::make('Content', 'plain_content')
                ])->dependsOn('type', "plain")
            ])
    ];
}

If you now have for example the following input data:

  • Type: "html", Content: "html 1"
  • Type: "plain", Content: "Plain 1"
  • Type: "plain", Content: "Plain 2"

You get DB entry like this:

[{
    "layout": "html",
    "key": "2244b3b27a11678a",
    "attributes": {
        "type": "html",
        "html_content": "<div>html 1<\/div>"
    }
}, {
    "layout": "html",
    "key": "8852edff81ca0ed3",
    "attributes": {
        "type": "plain",
        "plain_content": "Plain 1"
    }
}, {
    "layout": "html",
    "key": "668ca9a911074e49",
    "attributes": {
        "type": "plain",
        "plain_content": "Plain 2"
    }
}]

But I get a result like this, on the edit form

  • Type: "html", Content: ""
  • Type: "plain", Content: "Plain 2"
  • Type: "plain", Content: "Plain 2"

and on detail view as well:

image

@patrickleemsantos
Copy link

Any update on this?

@iBet7o
Copy link

iBet7o commented May 19, 2020

I have the following Preset which works fine when creating a record.

image

But the log detail shows the following error.

image

And when editing the resource, the first field doesn't display correctly.

image

Does anyone know if the problem is already identified?

Regards,

@deckchan
Copy link

Any update?

@apepindev
Copy link

@iBet7o I'm getting the same property of non-object error with a layout using flexible-content. In the resolveForDisplay method in the NovaDependencyContainer class, the $resource var being passed through is an array where is should be a resource instance. I have the HasDependencies trait on my resource.

This is my layout using Nova 2.12.0, felxible-content 0.2.3 and 1.2.11 of this package.

<?php

namespace App\Nova\Flexible\Layouts;

use Epartment\NovaDependencyContainer\NovaDependencyContainer;
use Laravel\Nova\Fields\Select;
use Laravel\Nova\Fields\Text;
use OwenMelbz\RadioField\RadioButton;
use Whitecube\NovaFlexibleContent\Layouts\Layout;

class Button extends Layout
{
    /**
     * The layout's unique identifier
     *
     * @var string
     */
    protected $name = 'button';

    /**
     * The displayed title
     *
     * @var string
     */
    protected $title = 'Button';

    /**
     * Get the fields displayed by the layout.
     *
     * @return array
     */
    public function fields()
    {
        return [
            Text::make('Button Label', 'btnlabel'),
            RadioButton::make('Type', 'type')
                ->options([
                    1 => ['Route' => 'Choose from a pre-defined set of site routes.'],
                    2 => ['URL' => 'Define a full URL for the link.']
                ])
                ->default('')
                ->rules('required')
                ->stack()
                ->marginBetween()
                ->skipTransformation(),
            NovaDependencyContainer::make([
                Select::make('Route', 'route')->options([
                    'home' => 'Homepage',
                    'login' => 'Login',
                    'register' => 'Registration'
                ])
            ])->dependsOn('type', 1),
            NovaDependencyContainer::make([
                Text::make('URL', 'url')
            ])->dependsOn('type', 2),
            Select::make('Alignment', 'align')
                ->options([
                    'start' => 'Left',
                    'center' => 'Middle'
                ])
        ];
    }
}

@wize-wiz
Copy link
Contributor

wize-wiz commented Jul 2, 2020

@Paradiddley try to use the development branch, only branch so far that supports flexible content and inline relationship.

@apepindev
Copy link

@wize-wiz I've updated the package to use that branch but I get another error Call to undefined method stdClass::getAttribute(). There's a MorphTo fix in there that's expecting the $resource to be a Resource instance but it's type casted to an stdClass. I've cloned that branch and had a look and just added a condition before it. This has fixed it for me. Let me know if you're happy for me to push into the same branch.

if ($resource instanceof Resource) {
    // @todo: quickfix for MorphTo
    $morphable_attribute = $resource->getAttribute($dependency['property'].'_type');
    if ($morphable_attribute !== null && Str::endsWith($morphable_attribute, '\\'.$dependency['value'])) {
        $this->meta['dependencies'][$index]['satisfied'] = true;
        continue;
    }
}

@wize-wiz
Copy link
Contributor

@Paradiddley sure PR would be great 👍

@apepindev
Copy link

@wize-wiz sure thing, here you go #123

@albertgpdevtrioteca
Copy link

@wize-wiz any update?

@albertgpdevtrioteca
Copy link

albertgpdevtrioteca commented Aug 28, 2020

Hello @dividy, @bernhardh, @wize-wiz.

After 5 days of hard fight against the bug, we have managed to solve it. The problem comes because NovaDependencyContainer within flexible overwrites the values of its fields with the value of the last one.
To solve this, what we have done is to pass to the Fleixble constructor the fields to null.
In the layout extension file we have done the following:

   /*
     * Get a cloned instance with set values
     *
     * @param  string  $key
     * @param  array  $attributes
     * @return \Whitecube\NovaFlexibleContent\Layouts\Layout
     */
    public function duplicateAndHydrate($key, array $attributes = [])
    {
        return new static(
            $this->title,
            $this->name,
            null,
            $key,
            $attributes
        );
    }

I hope it helps you. Greetings

@martijn94
Copy link

Running into the same issue, the fixes (including the open PR) seem to fix the issue. Any ETA on a release?

@Blindmikey
Copy link

I'm getting the same issue I believe, though the error message nova throws is now Attempt to read property "override" on array

@Blindmikey
Copy link

Blindmikey commented Mar 31, 2021

Resolved with @albertgpdevtrioteca 's suggestion combined with @Paradiddley 's
And a typecast of the array to an object with

...
if ( is_array( $resource ) ) { $resource = (object)$resource; }
if ($dependency['value'] == $resource->{$dependency['property']}) {
...

@mateusgalasso
Copy link

Hello @dividy, @bernhardh, @wize-wiz.

After 5 days of hard fight against the bug, we have managed to solve it. The problem comes because NovaDependencyContainer within flexible overwrites the values of its fields with the value of the last one.
To solve this, what we have done is to pass to the Fleixble constructor the fields to null.
In the layout extension file we have done the following:

   /*
     * Get a cloned instance with set values
     *
     * @param  string  $key
     * @param  array  $attributes
     * @return \Whitecube\NovaFlexibleContent\Layouts\Layout
     */
    public function duplicateAndHydrate($key, array $attributes = [])
    {
        return new static(
            $this->title,
            $this->name,
            null,
            $key,
            $attributes
        );
    }

I hope it helps you. Greetings

How and where did you do that?

@kbellpostman
Copy link

@stonkeep copy pasted that code into my layout... works :D Thanks @albertgpdevtrioteca !!!
image

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
compatibility Compatibility in combination with other packages
Projects
None yet
Development

No branches or pull requests