Cómo agregar campos personalizados a modelos

He actualizado la guía de Campos Personalizados de Temas a Discourse 3.4.0. Actualizaré la guía de categorías la próxima semana.

4 Me gusta

Hola @angus, ¡gracias por el plugin category-custom-fields!

Sin embargo, los valores no se almacenan al hacer clic en ckbdGuardar Categoríakbd:

  • La casilla de verificación de tu ejemplo sin modificar vuelve inmediatamente a sin marcar.
  • El campo personalizado no se guarda en la base de datos (lo monitoreé).

¡La imagen muestra una interfaz de usuario con opciones para “configuración de mi_campo”, con una casilla de verificación etiquetada como “mi_campo” y un botón de “Guardar Categoría” en la parte inferior. (Por IA)|422x390, 50%](upload://2pIlhH9fiTvKqIDMTleGVIzF3Ew.png)

No recibo ningún error.

¿Podrías ayudarme a averiguar esto? No puedo encontrar ninguna causa.

¿Existe alguna forma de asegurar en el lado del servidor que los campos personalizados sean obligatorios?

En un plugin, normalmente usarás el modelo ModelCustomField para añadir tus propios datos.

¿Puedes contarme más sobre lo que estás intentando hacer?

He añadido los campos personalizados y puedo guardarlos en la base de datos en una tabla personalizada. Sin embargo, quiero que estos campos personalizados sean obligatorios tanto en el lado del cliente como en el del servidor. En el lado del cliente, todavía es relativamente fácil. En el lado del servidor, ¿hay una forma estándar de validar que todos los campos personalizados estén llenos y luego solo permitir que se cree el tema? Ahora mismo, incluso si los campos personalizados están vacíos, el tema se crea sin ellos.

Ah. Eso es fácil, pero no soy lo suficientemente bueno en Rails para decirte cómo. Pero tendrás tu código detrás de un callback (Active Record Callbacks — Ruby on Rails Guides) que se llama antes de crear y fallará si tus campos no están ahí.

Hi everyone,

I set up a plugin based on Topic Custom Fields and everything was working fine until I updated Discourse to version 3.6.0.beta1-dev.

  • Topic list => OK, the columns appear correctly in the listing
  • Topic title => OK, the columns appear correctly under the topic title
  • Topic composer => KO, the fields don’t appear and I can’t compose and validate the message.

Here is the message encountered:

index.js:104 DEBUG: -------------------------------
index.js:104 DEBUG: Ember : 6.6.0
index.js:104 DEBUG: -------------------------------
app.js:271 ℹ️ Discourse v3.6.0.beta1-dev — https://github.com/discourse/discourse/commits/1d5b82ed51 — Ember v6.6.0
dev-tools.js:47 Loading Discourse dev tools...
contentCommunicatorMain.js:1 -- pf - starting script detection
dev-tools.js:55 Loaded Discourse dev tools. Run `disableDevTools()` in console to disable.
index.js:104 DEBUG: For more advanced debugging, install the Ember Inspector from https://chrome.google.com/webstore/detail/ember-inspector/bmdblncegkenkacieihfhpjfppoconhi
index.js:4148 

Error occurred:

- While rendering:
  {{outlet}} for -top-level
    -top-level
      {{outlet}} for application
        application
          (unknown template-only component)
            DiscourseRoot
              ComposerContainer
                ComposerBody
                  ComposerEditor
                    DEditor
                      PluginOutletComponent
                        TopicVersionComposer
                          topic-custom-field-input
                            Input
execute @ index.js:4148
index.js:3391 

Error occurred:
execute @ index.js:3391
index.js:85 Uncaught (in promise) Error: Attempted to resolve a helper in a strict mode template, but that value was not in scope: action
    at lookupBuiltInHelper (index.js:85:30)
    at index.js:253:60
    at encodeOp (index.js:266:8)
    at pushOp (index.js:1210:5)
    at index.js:636:33
    at Compilers.compile (index.js:448:14)
    at expr (index.js:461:43)
    at CompilePositional (index.js:614:47)
    at SimpleArgs (index.js:595:15)
    at index.js:1064:12
    at index.js:214:11
    at encodeOp (index.js:240:7)
    at pushOp (index.js:1210:5)
    at index.js:1063:35
    at Compilers.compile (index.js:448:14)
    at compileStatements (index.js:1212:49)
    at index.js:1191:18
    at CompilableTemplateImpl.compile (index.js:1193:6)
    at VM.compile (index.js:3771:31)
    at Object.evaluate (index.js:506:25)
    at Object.evaluate (index.js:103:106)
    at LowLevelVM.evaluateSyscall (index.js:2873:20)
    at LowLevelVM.evaluateInner (index.js:2852:64)
    at LowLevelVM.evaluateOuter (index.js:2849:10)
    at VM.next (index.js:4167:45)
    at VM._execute (index.js:4157:21)
    at VM.execute (index.js:4137:26)
    at TryOpcode.handleException (index.js:3450:19)
    at UpdatingVMFrame.handleException (index.js:3592:52)
    at UpdatingVM.throw (index.js:3414:16)
    at Assert.evaluate (index.js:565:42)
    at UpdatingVM._execute (index.js:3401:34)
    at index.js:3384:51
    at push.../../../../../../../node_modules/.pnpm/ember-source@6.6.0_patch_hash=tyhbf7f4uxnr3gt4x2tdcudbva_@glimmer+component@2.0.0_rsvp@4.8.5/node_modules/ember-source/dist/packages/@glimmer/validator/index.js.debug.runInTrackingTransaction (index.js:44:19)
    at UpdatingVM.execute (index.js:3384:15)
    at RenderResultImpl.rerender (index.js:3610:8)
    at index-BCp6wOJU.js:4639:55
    at RootState.render (index-BCp6wOJU.js:4600:9)
    at index-BCp6wOJU.js:4934:16
    at inTransaction (index.js:2414:7)
    at Renderer._renderRoots (index-BCp6wOJU.js:4914:20)
    at Renderer._renderRootsTransaction (index-BCp6wOJU.js:4962:12)
    at Renderer._revalidate (index-BCp6wOJU.js:4995:10)
    at invoke (index.js:262:14)
    at Queue.flush (index.js:180:11)
    at DeferredActionQueues.flush (index.js:334:19)
    at Backburner._end (index.js:762:32)
    at Backburner._boundAutorunEnd (index.js:499:12)
index-BCp6wOJU.js:4608 Attempted to rerender, but the Ember application has had an unrecoverable error occur during render. You should reload the application after fixing the cause of the error.
fn @ index-BCp6wOJU.js:4608
index-BCp6wOJU.js:4608 Attempted to rerender, but the Ember application has had an unrecoverable error occur during render. You should reload the application after fixing the cause of the error.
fn @ index-BCp6wOJU.js:4608
index-BCp6wOJU.js:4608 Attempted to rerender, but the Ember application has had an unrecoverable error occur during render. You should reload the application after fixing the cause of the error.
fn @ index-BCp6wOJU.js:4608
index-BCp6wOJU.js:4608 Attempted to rerender, but the Ember application has had an unrecoverable error occur during render. You should reload the application after fixing the cause of the error.
fn @ index-BCp6wOJU.js:4608
index-BCp6wOJU.js:4608 Attempted to rerender, but the Ember application has had an unrecoverable error occur during render. You should reload the application after fixing the cause of the error.
fn @ index-BCp6wOJU.js:4608
index-BCp6wOJU.js:4608 Attempted to rerender, but the Ember application has had an unrecoverable error occur during render. You should reload the application after fixing the cause of the error.
fn @ index-BCp6wOJU.js:4608
  • Topic edit view => KO, the fields don’t appear and I can’t validate the title modification.

Here is the message encountered -pretty much the same as the previous one- :

index.js:4148 

Error occurred:

- While rendering:
  {{outlet}} for -top-level
    -top-level
      {{outlet}} for application
        application
          (unknown template-only component)
            DiscourseRoot
              {{outlet}} for topic
                topic
                  (unknown template-only component)
                    DiscourseTopic
                      TopicTitle
                        PluginOutletComponent
                          TopicVersionEditTopic
                            topic-custom-field-input
                              Input


execute @ index.js:4148
handleException @ index.js:3450
handleException @ index.js:3592
throw @ index.js:3414
evaluate @ index.js:565
_execute @ index.js:3401
(anonymous) @ index.js:3384
push.../../../../../../../node_modules/.pnpm/ember-source@6.6.0_patch_hash=tyhbf7f4uxnr3gt4x2tdcudbva_@glimmer+component@2.0.0_rsvp@4.8.5/node_modules/ember-source/dist/packages/@glimmer/validator/index.js.debug.runInTrackingTransaction @ index.js:44
execute @ index.js:3384
rerender @ index.js:3610
(anonymous) @ index-BCp6wOJU.js:4639
(anonymous) @ index-BCp6wOJU.js:4600
(anonymous) @ index-BCp6wOJU.js:4934
inTransaction @ index.js:2414
_renderRoots @ index-BCp6wOJU.js:4914
_renderRootsTransaction @ index-BCp6wOJU.js:4962
_revalidate @ index-BCp6wOJU.js:4995
invoke @ index.js:262
flush @ index.js:180
flush @ index.js:334
_end @ index.js:762
Backburner._boundAutorunEnd @ index.js:499
Promise.then
iterations @ index.js:18
flush @ index.js:29
_scheduleAutorun @ index.js:928
_end @ index.js:768
Backburner._boundAutorunEnd @ index.js:499
Promise.then
iterations @ index.js:18
flush @ index.js:29
_scheduleAutorun @ index.js:928
_end @ index.js:768
Backburner._boundAutorunEnd @ index.js:499
Promise.then
iterations @ index.js:18
flush @ index.js:29
_scheduleAutorun @ index.js:928
_ensureInstance @ index.js:919
ensureInstance @ index.js:731
scheduleRevalidate @ index-BCp6wOJU.js:3609
dirtyTag @ index.js:229
dirtyTagFor @ index.js:287
markObjectAsDirty @ cache-fCezwMOy.js:49
notifyPropertyChange @ cache-fCezwMOy.js:745
_setProp @ property_set-2JtwI-ab.js:66
set @ property_set-2JtwI-ab.js:42
set @ observable.js:27
editTopic @ topic.js:376
index.js:3391 

Error occurred:

execute @ index.js:3391
rerender @ index.js:3610
(anonymous) @ index-BCp6wOJU.js:4639
(anonymous) @ index-BCp6wOJU.js:4600
(anonymous) @ index-BCp6wOJU.js:4934
inTransaction @ index.js:2414
_renderRoots @ index-BCp6wOJU.js:4914
_renderRootsTransaction @ index-BCp6wOJU.js:4962
_revalidate @ index-BCp6wOJU.js:4995
invoke @ index.js:262
flush @ index.js:180
flush @ index.js:334
_end @ index.js:762
Backburner._boundAutorunEnd @ index.js:499
Promise.then
iterations @ index.js:18
flush @ index.js:29
_scheduleAutorun @ index.js:928
_end @ index.js:768
Backburner._boundAutorunEnd @ index.js:499
Promise.then
iterations @ index.js:18
flush @ index.js:29
_scheduleAutorun @ index.js:928
_end @ index.js:768
Backburner._boundAutorunEnd @ index.js:499
Promise.then
iterations @ index.js:18
flush @ index.js:29
_scheduleAutorun @ index.js:928
_ensureInstance @ index.js:919
ensureInstance @ index.js:731
scheduleRevalidate @ index-BCp6wOJU.js:3609
dirtyTag @ index.js:229
dirtyTagFor @ index.js:287
markObjectAsDirty @ cache-fCezwMOy.js:49
notifyPropertyChange @ cache-fCezwMOy.js:745
_setProp @ property_set-2JtwI-ab.js:66
set @ property_set-2JtwI-ab.js:42
set @ observable.js:27
editTopic @ topic.js:376
5:1 Autofocus processing was blocked because a document already has a focused element.
index.js:85 Uncaught (in promise) Error: Attempted to resolve a helper in a strict mode template, but that value was not in scope: action
    at lookupBuiltInHelper (index.js:85:30)
    at index.js:253:60
    at encodeOp (index.js:266:8)
    at pushOp (index.js:1210:5)
    at index.js:636:33
    at Compilers.compile (index.js:448:14)
    at expr (index.js:461:43)
    at CompilePositional (index.js:614:47)
    at SimpleArgs (index.js:595:15)
    at index.js:1064:12
    at index.js:214:11
    at encodeOp (index.js:240:7)
    at pushOp (index.js:1210:5)
    at index.js:1063:35
    at Compilers.compile (index.js:448:14)
    at compileStatements (index.js:1212:49)
    at index.js:1191:18
    at CompilableTemplateImpl.compile (index.js:1193:6)
    at VM.compile (index.js:3771:31)
    at Object.evaluate (index.js:506:25)
    at Object.evaluate (index.js:103:106)
    at LowLevelVM.evaluateSyscall (index.js:2873:20)
    at LowLevelVM.evaluateInner (index.js:2852:64)
    at LowLevelVM.evaluateOuter (index.js:2849:10)
    at VM.next (index.js:4167:45)
    at VM._execute (index.js:4157:21)
    at VM.execute (index.js:4137:26)
    at TryOpcode.handleException (index.js:3450:19)
    at UpdatingVMFrame.handleException (index.js:3592:52)
    at UpdatingVM.throw (index.js:3414:16)
    at Assert.evaluate (index.js:565:42)
    at UpdatingVM._execute (index.js:3401:34)
    at index.js:3384:51
    at push.../../../../../../../node_modules/.pnpm/ember-source@6.6.0_patch_hash=tyhbf7f4uxnr3gt4x2tdcudbva_@glimmer+component@2.0.0_rsvp@4.8.5/node_modules/ember-source/dist/packages/@glimmer/validator/index.js.debug.runInTrackingTransaction (index.js:44:19)
    at UpdatingVM.execute (index.js:3384:15)
    at RenderResultImpl.rerender (index.js:3610:8)
    at index-BCp6wOJU.js:4639:55
    at RootState.render (index-BCp6wOJU.js:4600:9)
    at index-BCp6wOJU.js:4934:16
    at inTransaction (index.js:2414:7)
    at Renderer._renderRoots (index-BCp6wOJU.js:4914:20)
    at Renderer._renderRootsTransaction (index-BCp6wOJU.js:4962:12)
    at Renderer._revalidate (index-BCp6wOJU.js:4995:10)
    at invoke (index.js:262:14)
    at Queue.flush (index.js:180:11)
    at DeferredActionQueues.flush (index.js:334:19)
    at Backburner._end (index.js:762:32)
    at Backburner._boundAutorunEnd (index.js:499:12)
lookupBuiltInHelper @ index.js:85
(anonymous) @ index.js:253
encodeOp @ index.js:266
pushOp @ index.js:1210
(anonymous) @ index.js:636
compile @ index.js:448
expr @ index.js:461
CompilePositional @ index.js:614
SimpleArgs @ index.js:595
(anonymous) @ index.js:1064
(anonymous) @ index.js:214
encodeOp @ index.js:240
pushOp @ index.js:1210
(anonymous) @ index.js:1063
compile @ index.js:448
compileStatements @ index.js:1212
(anonymous) @ index.js:1191
compile @ index.js:1193
compile @ index.js:3771
(anonymous) @ index.js:506
evaluate @ index.js:103
evaluateSyscall @ index.js:2873
evaluateInner @ index.js:2852
evaluateOuter @ index.js:2849
next @ index.js:4167
_execute @ index.js:4157
execute @ index.js:4137
handleException @ index.js:3450
handleException @ index.js:3592
throw @ index.js:3414
evaluate @ index.js:565
_execute @ index.js:3401
(anonymous) @ index.js:3384
push.../../../../../../../node_modules/.pnpm/ember-source@6.6.0_patch_hash=tyhbf7f4uxnr3gt4x2tdcudbva_@glimmer+component@2.0.0_rsvp@4.8.5/node_modules/ember-source/dist/packages/@glimmer/validator/index.js.debug.runInTrackingTransaction @ index.js:44
execute @ index.js:3384
rerender @ index.js:3610
(anonymous) @ index-BCp6wOJU.js:4639
(anonymous) @ index-BCp6wOJU.js:4600
(anonymous) @ index-BCp6wOJU.js:4934
inTransaction @ index.js:2414
_renderRoots @ index-BCp6wOJU.js:4914
_renderRootsTransaction @ index-BCp6wOJU.js:4962
_revalidate @ index-BCp6wOJU.js:4995
invoke @ index.js:262
flush @ index.js:180
flush @ index.js:334
_end @ index.js:762
Backburner._boundAutorunEnd @ index.js:499
Promise.then
iterations @ index.js:18
flush @ index.js:29
_scheduleAutorun @ index.js:928
_end @ index.js:768
Backburner._boundAutorunEnd @ index.js:499
Promise.then
iterations @ index.js:18
flush @ index.js:29
_scheduleAutorun @ index.js:928
_end @ index.js:768
Backburner._boundAutorunEnd @ index.js:499
Promise.then
iterations @ index.js:18
flush @ index.js:29
_scheduleAutorun @ index.js:928
_ensureInstance @ index.js:919
ensureInstance @ index.js:731
scheduleRevalidate @ index-BCp6wOJU.js:3609
dirtyTag @ index.js:229
dirtyTagFor @ index.js:287
markObjectAsDirty @ cache-fCezwMOy.js:49
notifyPropertyChange @ cache-fCezwMOy.js:745
_setProp @ property_set-2JtwI-ab.js:66
set @ property_set-2JtwI-ab.js:42
set @ observable.js:27
editTopic @ topic.js:376

Are any of you experiencing the same problem?

1 me gusta

Hola @cdervout,

Problema
El componente de entrada de campo personalizado del tema utilizaba la sintaxis heredada:

{{on "change" (action @onChangeField value="target.value")}}
  • Esta sintaxis (action …) no es compatible con los componentes Glimmer modernos.
  • En consecuencia, el campo no se renderizaba en absoluto en el compositor.

Solución
Se reemplazó la sintaxis antigua por una acción Glimmer moderna:

{{on "input" this.handleInputChange}}

Y se agregó el método JS correspondiente:

@action
handleInputChange(event) {
  this.args.onChangeField(event.target.value);
}
  • Esto asegura que el campo se renderice correctamente en el compositor.

Código del componente refactorizado

import Component from "@glimmer/component";
import { Input, Textarea } from "@ember/component";
import { on } from "@ember/modifier";
import { readOnly } from "@ember/object/computed";
import { service } from "@ember/service";
import { eq } from "truth-helpers";
import i18n from "discourse-common/helpers/i18n";
import { action } from "@ember/object";

export default class TopicCustomFieldInput extends Component {
  @service siteSettings;
  @readOnly("siteSettings.topic_custom_field_name") fieldName;
  @readOnly("siteSettings.topic_custom_field_type") fieldType;

  @action
  handleInputChange(event) {
    this.args.onChangeField(event.target.value);
  }

  <template>
    {{#if (eq this.fieldType "boolean")}}
      <Input
        @type="checkbox"
        @checked={{@fieldValue}}
        {{on "input" this.handleInputChange}}
      />
      <span>{{this.fieldName}}</span>
    {{/if}}

    {{#if (eq this.fieldType "integer")}}
      <Input
        @type="number"
        @value={{@fieldValue}}
        placeholder={{i18n
          "topic_custom_field.placeholder"
          field=this.fieldName
        }}
        class="topic-custom-field-input small"
        {{on "input" this.handleInputChange}}
      />
    {{/if}}

    {{#if (eq this.fieldType "string")}}
      <Input
        @type="text"
        @value={{@fieldValue}}
        placeholder={{i18n
          "topic_custom_field.placeholder"
          field=this.fieldName
        }}
        class="topic-custom-field-input large"
        {{on "input" this.handleInputChange}}
      />
    {{/if}}

    {{#if (eq this.fieldType "json")}}
      <Textarea
        @value={{@fieldValue}}
        {{on "input" this.handleInputChange}}
        placeholder={{i18n
          "topic_custom_field.placeholder"
          field=this.fieldName
        }}
        class="topic-custom-field-textarea"
      />
    {{/if}}
  </template>
}

EDIT: He abierto un PR al respecto

3 Me gusta

¡Gracias, todo funciona bien!

He adaptado el código en el caso de que el campo sea una casilla de verificación. Para recuperar el valor, tuve que usar event.target.checked en lugar de event.target.value.

2 Me gusta