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

WIP If the model contains errors, display inline errors in jsoneditor #60

Open
wants to merge 7 commits into
base: master
Choose a base branch
from
7 changes: 7 additions & 0 deletions src/models/crud/WidgetContent.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
namespace hrzg\widget\models\crud;

use hrzg\widget\models\crud\base\Widget as BaseWidget;
use hrzg\widget\validators\ClientSideJsonValidator;
use hrzg\widget\widgets\Cell;
use JsonSchema\Validator;
use yii\behaviors\TimestampBehavior;
Expand Down Expand Up @@ -182,6 +183,12 @@ public function rules()
'operator' => '>',
'type' => 'datetime'
];

$rules[] = [
'default_properties_json',
ClientSideJsonValidator::class
];

// add json schema validation if enabled in module
if (!empty(\Yii::$app->controller->module->validateContentSchema)) {
$rules['validate_properties_json'] = [
Expand Down
7 changes: 7 additions & 0 deletions src/models/crud/WidgetContentTranslation.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@

use hrzg\widget\models\crud\base\Widget;
use hrzg\widget\models\crud\base\WidgetTranslation;
use hrzg\widget\validators\ClientSideJsonValidator;
use JsonSchema\Validator;
use yii\caching\TagDependency;
use yii\helpers\Json;
Expand All @@ -30,6 +31,12 @@ class WidgetContentTranslation extends WidgetTranslation
public function rules()
{
$rules = parent::rules();

$rules[] = [
'default_properties_json',
ClientSideJsonValidator::class
];

// add json schema validation if enabled in module
if (!empty(\Yii::$app->controller->module->validateContentSchema)) {
$rules['validate_properties_json'] = [
Expand Down
53 changes: 53 additions & 0 deletions src/validators/ClientSideJsonValidator.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

namespace hrzg\widget\validators;

use yii\validators\Validator;

class ClientSideJsonValidator extends Validator
{
public function validateValue($value)
{
return [];
}

public function clientValidateAttribute($model, $attribute, $view)
{
return <<<JS
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does it work, when using multiple JSONEditor on the same Page?

Copy link
Contributor Author

@germanbisurgi germanbisurgi Mar 1, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The ClientSideJsonValidator works with the first json-editor it finds. Currently, Widgets2 uses only one json-editor at a time.

The publication module relies on Widgets2 as a dependency, I manually tested it and found no errors. It's worth noting that the publication module doesn't actively use the ClientSideJsonValidator. Instead, relies on the the regular json-editor error messages during interaction.

If you have any potential scenarios that could conflict with this pull request, please let me know. I know this PR could create more issues than it solves :)

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I added an extra check for the editor. In any case, if for some reason an error occurs during this client validation step, The page will just submit the form normally (no AJAX) and proceed with the normal flow, meaning backend validation and showing an error summary

Copy link
Member

@schmunk42 schmunk42 Mar 5, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is ClientSideJsonValidator specific to widgets2 or would it actually belong to https://github.com/dmstr/yii2-json-editor ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is specific to widgets2

const editor = window.jsonEditors[0]
const errors = editor.validate()


// collect error messages for this validator
errors.forEach(function (error) {
const invalidEditor = editor.getEditor(error.path)
const field = invalidEditor.schema.title || error.path
const message = field + ': ' + error.message
messages.push(message)
})

// coerce json-editor to display own inline error messages
Object.values(editor.editors).forEach(function (editor) {
editor.is_dirty = true
})

editor.root.showValidationErrors(errors)

// remove the 'has-error' class from editor container. Using * selector because
// the class name can change from model to mode but the attribute in this case
// is always "default_properties_json"
const targetNode = document.querySelector('[class*="default_properties_json"]')

const observer = new MutationObserver((mutations) => {
mutations.forEach(() => {
if (targetNode.classList.contains('has-error')) {
targetNode.classList.remove('has-error')
observer.disconnect()
}
})
})

observer.observe(targetNode, { attributes: true, attributeFilter: ['class'] })
JS;
}
}
13 changes: 10 additions & 3 deletions src/views/crud/widget-translation/_form.php
Original file line number Diff line number Diff line change
Expand Up @@ -90,15 +90,22 @@
<?= $form->errorSummary($model) ?>

<?php \yii\widgets\Pjax::begin(['id' => 'pjax-widget-form']) ?>
<?= $form->field($model, 'default_properties_json')->label(false)
<?= $form->field($model, 'default_properties_json', [
'template' => '{input}'
])->label(false)
->widget(\dmstr\jsoneditor\JsonEditorWidget::class, [
'id' => 'editor',
'schema' => $schema,
'clientOptions' => [
'theme' => 'bootstrap3',
'iconlib' => 'fontawesome4',
'disable_collapse' => true,
'disable_properties' => true,
'keep_oneof_values' => false
'disable_properties' => false,
"no_additional_properties" => false,
'keep_oneof_values' => false,
'expand_height' => true,
'ajax' => !empty(\Yii::$app->controller->module->allowAjaxInSchema) ? true : false,
'show_errors' => $model->hasErrors() ? 'always' : 'interaction'
],
]); ?>
<?php \yii\widgets\Pjax::end() ?>
Expand Down
2 changes: 1 addition & 1 deletion src/views/crud/widget-translation/update.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
[
'id' => 'widget-update',
'layout' => 'default',
'enableClientValidation' => false,
'enableClientValidation' => true,
'errorSummaryCssClass' => 'error-summary alert alert-error',
'fieldConfig' => [
'horizontalCssClasses' => [
Expand Down
5 changes: 4 additions & 1 deletion src/views/crud/widget/_form.php
Original file line number Diff line number Diff line change
Expand Up @@ -114,7 +114,9 @@


<?php \yii\widgets\Pjax::begin(['id' => 'pjax-widget-form']) ?>
<?= $form->field($model, 'default_properties_json')->label(false)
<?= $form->field($model, 'default_properties_json', [
'template' => '{input}'
])->label(false)
->widget(\dmstr\jsoneditor\JsonEditorWidget::className(), [
'id' => 'editor',
'schema' => $schema,
Expand All @@ -127,6 +129,7 @@
'keep_oneof_values' => false,
'expand_height' => true,
'ajax' => !empty(\Yii::$app->controller->module->allowAjaxInSchema) ? true : false,
'show_errors' => $model->hasErrors() ? 'always' : 'interaction'
],
]); ?>
<?php \yii\widgets\Pjax::end() ?>
Expand Down
2 changes: 1 addition & 1 deletion src/views/crud/widget/create.php
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,7 @@
[
'id' => 'widget-create',
'layout' => 'default',
'enableClientValidation' => false,
'enableClientValidation' => true,
'errorSummaryCssClass' => 'error-summary alert alert-error',
'fieldConfig' => [
'horizontalCssClasses' => [
Expand Down
2 changes: 1 addition & 1 deletion src/views/crud/widget/update.php
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,7 @@
[
'id' => 'widget-update',
'layout' => 'default',
'enableClientValidation' => false,
'enableClientValidation' => true,
'errorSummaryCssClass' => 'error-summary alert alert-error',
'fieldConfig' => [
'horizontalCssClasses' => [
Expand Down