Come aggiungere campi personalizzati ai modelli

Ho aggiornato la guida dei Campi Personalizzati dell’Argomento a Discourse 3.4.0. Aggiornerò la guida delle categorie la prossima settimana.

4 Mi Piace

Ciao @angus, grazie per il plugin category-custom-fields!

Tuttavia, i valori non vengono salvati quando si fa clic su Salva categoria:

  • La casella di controllo del tuo esempio non modificato torna immediatamente a non selezionata.
  • Il campo personalizzato non viene salvato nel database (l’ho monitorato).

Non ricevo errori.

Potresti aiutarmi a capire? Non riesco a trovare alcuna causa.

C’è un modo per assicurarsi lato server che i campi personalizzati siano obbligatori?

In un plugin, di solito si utilizza il modello ModelCustomField per aggiungere i propri dati.

Puoi dirmi di più su cosa stai cercando di fare?

Ho aggiunto i campi personalizzati e sono in grado di salvarli nel database in una tabella personalizzata. Tuttavia, voglio rendere questi campi personalizzati obbligatori sia lato client che lato server. Sul lato client è ancora relativamente facile. Sul lato server, esiste un modo standard per convalidare che tutti i campi personalizzati siano compilati e quindi consentire solo la creazione dell’argomento. Al momento, anche se i campi personalizzati sono vuoti, l’argomento viene creato senza di essi.

Ah. È facile, ma non sono abbastanza bravo con Rails per dirtelo. Ma avrai il tuo codice dietro un callback (Active Record Callbacks — Ruby on Rails Guides) che viene chiamato prima della creazione e fallirà se i tuoi campi non ci sono.

Ciao a tutti,

Ho configurato un plugin basato su Topic Custom Fields e tutto funzionava correttamente fino a quando ho aggiornato Discourse alla versione 3.6.0.beta1-dev.

  • Elenco argomenti => OK, le colonne vengono visualizzate correttamente nell’elenco
  • Titolo argomento => OK, le colonne vengono visualizzate correttamente sotto il titolo dell’argomento
  • Compositore argomento => KO, i campi non vengono visualizzati e non riesco a scrivere e inviare il messaggio.

Ecco il messaggio di errore riscontrato:

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 Caricamento strumenti di sviluppo Discourse...
contentCommunicatorMain.js:1 -- pf - avvio rilevamento script
dev-tools.js:55 Strumenti di sviluppo Discourse caricati. Esegui `disableDevTools()` nella console per disattivarli.
index.js:104 DEBUG: Per un debug più avanzato, installa Ember Inspector da https://chrome.google.com/webstore/detail/ember-inspector/bmdblncegkenkacieihfhpjfppoconhi
index.js:4148 

Si è verificato un errore:

- Durante il rendering:
  {{outlet}} per -top-level
    -top-level
      {{outlet}} per application
        application
          (componente sconosciuto solo template)
            DiscourseRoot
              ComposerContainer
                ComposerBody
                  ComposerEditor
                    DEditor
                      PluginOutletComponent
                        TopicVersionComposer
                          topic-custom-field-input
                            Input
execute @ index.js:4148
index.js:3391 

Si è verificato un errore:
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 Tentativo di ridisegno fallito, ma l'applicazione Ember ha rilevato un errore irreparabile durante il rendering. Dovresti ricaricare l'applicazione dopo aver corretto la causa dell'errore.
fn @ index-BCp6wOJU.js:4608
index-BCp6wOJU.js:4608 Tentativo di ridisegno fallito, ma l'applicazione Ember ha rilevato un errore irreparabile durante il rendering. Dovresti ricaricare l'applicazione dopo aver corretto la causa dell'errore.
fn @ index-BCp6wOJU.js:4608
index-BCp6wOJU.js:4608 Tentativo di ridisegno fallito, ma l'applicazione Ember ha rilevato un errore irreparabile durante il rendering. Dovresti ricaricare l'applicazione dopo aver corretto la causa dell'errore.
fn @ index-BCp6wOJU.js:4608
index-BCp6wOJU.js:4608 Tentativo di ridisegno fallito, ma l'applicazione Ember ha rilevato un errore irreparabile durante il rendering. Dovresti ricaricare l'applicazione dopo aver corretto la causa dell'errore.
fn @ index-BCp6wOJU.js:4608
index-BCp6wOJU.js:4608 Tentativo di ridisegno fallito, ma l'applicazione Ember ha rilevato un errore irreparabile durante il rendering. Dovresti ricaricare l'applicazione dopo aver corretto la causa dell'errore.
fn @ index-BCp6wOJU.js:4608
index-BCp6wOJU.js:4608 Tentativo di ridisegno fallito, ma l'applicazione Ember ha rilevato un errore irreparabile durante il rendering. Dovresti ricaricare l'applicazione dopo aver corretto la causa dell'errore.
fn @ index-BCp6wOJU.js:4608
  • Vista modifica argomento => KO, i campi non vengono visualizzati e non riesco a confermare la modifica del titolo.

Ecco il messaggio di errore riscontrato -praticamente identico al precedente-:

index.js:4148 

Si è verificato un errore:

- Durante il rendering:
  {{outlet}} per -top-level
    -top-level
      {{outlet}} per application
        application
          (componente sconosciuto solo template)
            DiscourseRoot
              {{outlet}} per topic
                topic
                  (componente sconosciuto solo template)
                    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 

Si è verificato un errore:

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 Elaborazione dell'autofocus bloccata perché il documento ha già un elemento focalizzato.
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

Qualcuno di voi sta riscontrando lo stesso problema?

1 Mi Piace

Ciao @cdervout,

Problema
Il componente di input del campo personalizzato dell’argomento utilizzava la sintassi legacy:

{{on "change" (action @onChangeField value="target.value")}}
  • Questa sintassi (action …) non è supportata nei componenti Glimmer moderni.
  • Di conseguenza, il campo non veniva affatto visualizzato nel composer.

Correzione
Sostituita la vecchia sintassi con un’azione Glimmer moderna:

{{on "input" this.handleInputChange}}

E aggiunti il metodo JS corrispondente:

@action
handleInputChange(event) {
  this.args.onChangeField(event.target.value);
}
  • Ciò garantisce che il campo venga visualizzato correttamente nel composer.

Codice del componente rifattorizzato

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>
}

MODIFICA: Ho aperto una PR per lo stesso

4 Mi Piace

Grazie, tutto funziona perfettamente!

Ho adattato il codice nel caso in cui il campo sia una casella di controllo. Per recuperare il valore, ho dovuto usare event.target.checked invece di event.target.value

2 Mi Piace