chasegiunta / craft-jason

A field type for displaying & editing JSON data.
Other
15 stars 11 forks source link

Add a getStaticHtml() function to fields/JasonField.php #147

Open stevecomrie opened 1 year ago

stevecomrie commented 1 year ago

I'm trying to use a Jason field inside Commerce attached to an order, and I was running into a situation where the field would not appear in the UI when reviewing an order, but it would appear when I tried to "Edit" the Order.

Took me a long time to figure out what was going on.

Turns out that unlike the content parts Craft, Commerce has kind of a "preview screen" when first reviewing the contents of an order so that admins don't accidentally change things without intentionally meaning to. This also applies to reviewing Drafts of non-Commerce entries as well.

Craft calls the getInputHtml() function when it needs to display a field that is ready to accept user input, but not when it wants to display the read only contents of a field.

When it wants the read only version it calls the getStaticHtml() function associated with each field - https://docs.craftcms.com/api/v3/craft-fields-baserelationfield.html#public-methods

This is a relatively trivial function to implement since Jason already has the functionality to display a field as read-only.

So for the most part, it's a straight-up duplication of getInputHtml() with a couple of namespace changes with forced settings on readonly and allowRawEditing

    public function getStaticHtml($value, ElementInterface $element = null): string {

        if (is_array($value)) {
            $json = Json::encode($value);
            $valid = true;
        } else {
            // Assume we're accessing from control panel
            $json = json_decode($value); 
            if ($json === null) {
                $json = $value;
                $valid = false;
            } else {
                $json = Json::encode($json);
                $valid = true;
            }
        }

        // Register our asset bundle
        Craft::$app->getView()->registerAssetBundle(JasonFieldAsset::class);

        // Get our id and namespace
        $id = Craft::$app->getView()->formatInputId($this->handle) . '-static';
        $namespacedId = Craft::$app->getView()->namespaceInputId($id);

        Craft::$app->getView()->registerJs("var staticEvent = new CustomEvent('build', { detail: '$namespacedId' }); window.dispatchEvent(staticEvent);");

        // Render the input template
        return Craft::$app->getView()->renderTemplate(
            'jason/_components/fields/JasonField_input',
            [
                'name' => $this->handle,
                'value' => $json,
                'valid' => $valid,
                'field' => $this,
                'id' => $id,
                'namespacedId' => $namespacedId,
                'readonly' => true,
                'allowRawEditing' => false
            ]
        );
    }

The above could absolutely be refactored so that you don't have as much duplication between the two functions, but this would be a great addition as-is in the meantime.

chasegiunta commented 1 year ago

@stevecomrie Interesting. Nice find. Care to PR this?

stevecomrie commented 1 year ago

No problem, but I'm probably also going to include this fix - https://github.com/chasegiunta/craft-jason/issues/108#issuecomment-1409429781

:)