Wie man benutzerdefinierte Felder zu Modellen hinzufügt

Ich habe die Anleitung für benutzerdefinierte Themafelder für Discourse 3.4.0 aktualisiert. Nächste Woche werde ich die Kategorieanleitung aktualisieren.

4 „Gefällt mir“

Hallo @angus, danke für das category-custom-fields Plugin!

Allerdings werden die Werte beim Klicken auf Kategorie speichern nicht gespeichert:

  • Die Checkbox aus deinem unveränderten Beispiel springt sofort zurück auf nicht angekreuzt.
  • Das benutzerdefinierte Feld wird nicht in der Datenbank gespeichert (ich habe das überwacht).

Ich erhalte keine Fehler.

Könntest du mir helfen, das herauszufinden? Ich kann keine Ursachen finden.

Gibt es eine Möglichkeit, serverseitig sicherzustellen, dass benutzerdefinierte Felder obligatorisch sind?

In einem Plugin verwendest du normalerweise das ModelCustomField-Modell, um deine eigenen Daten hinzuzufügen.

Kannst du mehr darüber sagen, was du zu erreichen versuchst?

Ich habe die benutzerdefinierten Felder hinzugefügt und kann sie in einer benutzerdefinierten Tabelle in der Datenbank speichern. Ich möchte diese benutzerdefinierten Felder jedoch sowohl auf der Client- als auch auf der Serverseite als obligatorisch festlegen. Auf der Clientseite ist dies noch relativ einfach. Gibt es auf der Serverseite eine Standardmethode, um zu überprüfen, ob alle benutzerdefinierten Felder ausgefüllt sind, und dann nur die Erstellung des Themas zuzulassen? Im Moment wird das Thema auch dann erstellt, wenn die benutzerdefinierten Felder leer sind.

Ah. Das ist einfach, aber ich bin nicht gut genug in Rails, um Ihnen zu sagen, wie. Aber Sie werden Ihren Code hinter einem Callback (Active Record Callbacks — Ruby on Rails Guides) haben, der vor dem Erstellen aufgerufen wird und fehlschlägt, wenn Ihre Felder nicht vorhanden sind.

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 „Gefällt mir“

Hallo @cdervout,

Problem
Die Eingabekomponente für benutzerdefinierte Themenfelder verwendete die alte Syntax:

{{on "change" (action @onChangeField value="target.value")}}
  • Diese (action …)-Syntax wird in modernen Glimmer-Komponenten nicht unterstützt.
  • Folglich wurde das Feld im Composer überhaupt nicht gerendert.

Korrektur
Die alte Syntax wurde durch eine moderne Glimmer-Aktion ersetzt:

{{on "input" this.handleInputChange}}

Und die entsprechende JS-Methode wurde hinzugefügt:

@action
handleInputChange(event) {
  this.args.onChangeField(event.target.value);
}
  • Dies stellt sicher, dass das Feld im Composer korrekt gerendert wird.

Überarbeiteter Komponenten-Code

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: Ich habe einen PR dafür erstellt

3 „Gefällt mir“

Danke, alles funktioniert einwandfrei!

Ich habe den Code für den Fall angepasst, dass das Feld eine Checkbox ist. Um den Wert abzurufen, musste ich event.target.checked anstelle von event.target.value verwenden.

2 „Gefällt mir“