瀏覽代碼

Fix value updates in ui.editor after client-side changes (#3346)

* introduce editor.js to fix value updates after client-side changes

* add pytest
Falko Schindler 9 月之前
父節點
當前提交
63deabfd84
共有 3 個文件被更改,包括 65 次插入4 次删除
  1. 38 0
      nicegui/elements/editor.js
  2. 9 3
      nicegui/elements/editor.py
  3. 18 1
      tests/test_editor.py

+ 38 - 0
nicegui/elements/editor.js

@@ -0,0 +1,38 @@
+export default {
+  template: `
+    <q-editor
+      ref="qRef"
+      v-bind="$attrs"
+      v-model="inputValue"
+    >
+      <template v-for="(_, slot) in $slots" v-slot:[slot]="slotProps">
+        <slot :name="slot" v-bind="slotProps || {}" />
+      </template>
+    </q-input>
+  `,
+  props: {
+    value: String,
+  },
+  data() {
+    return {
+      inputValue: this.value,
+      emitting: true,
+    };
+  },
+  watch: {
+    value(newValue) {
+      this.emitting = false;
+      this.inputValue = newValue;
+      this.$nextTick(() => (this.emitting = true));
+    },
+    inputValue(newValue) {
+      if (!this.emitting) return;
+      this.$emit("update:value", newValue);
+    },
+  },
+  methods: {
+    updateValue() {
+      this.inputValue = this.value;
+    },
+  },
+};

+ 9 - 3
nicegui/elements/editor.py

@@ -4,8 +4,9 @@ from .mixins.disableable_element import DisableableElement
 from .mixins.value_element import ValueElement
 
 
-class Editor(ValueElement, DisableableElement):
-    LOOPBACK = None
+class Editor(ValueElement, DisableableElement, component='editor.js'):
+    VALUE_PROP: str = 'value'
+    LOOPBACK = False
 
     def __init__(self,
                  *,
@@ -21,7 +22,12 @@ class Editor(ValueElement, DisableableElement):
         :param value: initial value
         :param on_change: callback to be invoked when the value changes
         """
-        super().__init__(tag='q-editor', value=value, on_value_change=on_change)
+        super().__init__(value=value, on_value_change=on_change)
         self._classes.append('nicegui-editor')
         if placeholder is not None:
             self._props['placeholder'] = placeholder
+
+    def _handle_value_change(self, value: Any) -> None:
+        super()._handle_value_change(value)
+        if self._send_update_on_value_change:
+            self.run_method('updateValue')

+ 18 - 1
tests/test_editor.py

@@ -1,3 +1,4 @@
+from selenium.webdriver.common.keys import Keys
 
 from nicegui import ui
 from nicegui.testing import Screen
@@ -8,7 +9,23 @@ def test_editor(screen: Screen):
     ui.markdown().bind_content_from(editor, 'value', backward=lambda v: f'HTML code:\n```\n{v}\n```')
 
     screen.open('/')
-    screen.find_by_class('q-editor__content').click()
+    screen.find_element(editor).click()
     screen.type('Hello\nworld!')
     screen.wait(0.5)
     screen.should_contain('Hello<div>world!</div>')
+
+
+def test_setting_value_twice(screen: Screen):
+    # https://github.com/zauberzeug/nicegui/issues/3217
+    editor = ui.editor(value='X')
+    ui.button('Reset').on_click(lambda: editor.set_value('X'))
+
+    screen.open('/')
+    screen.should_contain('X')
+
+    screen.find_element(editor).click()
+    screen.type(Keys.BACKSPACE + 'ABC')
+    screen.should_contain('ABC')
+
+    screen.click('Reset')
+    screen.should_contain('X')