Suggestion to use get/setText() instead of get/set() to avoid weird save/error issues
Opened this issue · 0 comments
options.onChange = function () {
var json = editor.get();
textarea.value=JSON.stringify(json);
}
The above piece of code has nasty behavior. According to json-editor docs, editor.get() throws an Exception when the editor doesn't contain a valid JSON value. Well, what are the implications? It saves the last valid JSON value. Few open issues are due to this behavior. For instance consider, #26 On the second attempt when clearing completely (assuming CTRL + A and Backspace), onChange triggers, and editor.get() throws exception failing to update widget.value. #47 The last known value in textarea.value is "", copy-pasting invalid json does not update its value due to the same reasons mentioned.
Possible Solution:
Changing <script> block in django_json_widget.html
<script>
(function() {
const container = document.getElementById("{{ widget.attrs.id }}");
const textarea = document.getElementById("{{ widget.attrs.id }}_textarea");
const options = {{ widget.options | safe }};
options.onChange = function () {
textarea.value = editor.getText();
}
const editor = new JSONEditor(container, options);
const json = textarea.value;
editor.setText(json);
document.getElementById("{{ widget.attrs.id }}").getElementsByClassName('jsoneditor-format')[0]?.click()
})();
</script>
Django's inbuilt form validation takes care of validating JSON text.
Hackaround (just in case changes doesn't reach code-base)
Define JSONFieldWidget as follow:
"""django_json_widget.widgets.JSONEditorWidget with custom template_name"""
from django_json_widget.widgets import JSONEditorWidget
class JSONFieldWidget(JSONEditorWidget):
template_name = 'widgets/json_field_widget.html'
Define json_field_widget.html in the templates/widgets folder as follow:
<div {% if not widget.attrs.style %}style="height:{{widget.height|default:'500px'}};width:{{widget.width|default:'90%'}};display:inline-block;"{% endif %}{% include "django/forms/widgets/attrs.html" %}></div>
<textarea id="{{widget.attrs.id}}_textarea" name="{{ widget.name }}" required="" style="display: none">{{ widget.value }}</textarea>
<script>
(function() {
const container = document.getElementById("{{ widget.attrs.id }}");
const textarea = document.getElementById("{{ widget.attrs.id }}_textarea");
const options = {{ widget.options | safe }};
options.onChange = function () {
textarea.value = editor.getText();
}
const editor = new JSONEditor(container, options);
const json = textarea.value;
editor.setText(json);
document.getElementById("{{ widget.attrs.id }}").getElementsByClassName('jsoneditor-format')[0]?.click()
})();
</script>
That is it! Use JSONFieldWidget in place of JSONEditorWidget