Thanks @keegan !
I think I got the plugin.rb file setup correctly, the loop looks correct.
However, I’m struggling on the topic-custom-field-initializer.js file. Here is my code for both files. Any pointers for the initializer.js file? I think I’m really close here, when creating a new topic, I am getting 1/3 fields, the listingDetails field but still missing the isClassifiedListing and listingStatus
enabled_site_setting :topic_custom_field_enabled
register_asset 'stylesheets/common.scss'
after_initialize do
fields = [
{ name: 'isClassifiedListing', type: 'boolean' },
{ name: 'listingStatus', type: 'string' },
{ name: "listingDetails", type: 'json' }
]
fields.each do |field|
register_topic_custom_field_type(field[:name], field[:type].to_sym)
add_to_class(:topic, field[:name].to_sym) do
if !custom_fields[field[:name]].nil?
custom_fields[field[:name]]
else
nil
end
end
add_to_class(:topic, "#{field[:name]}=") do |value|
custom_fields[field[:name]] = value
end
on(:topic_created) do |topic, opts, user|
topic.send("#{field[:name]}=".to_sym, opts[field[:name].to_sym])
topic.save!
end
PostRevisor.track_topic_field(field[:name].to_sym) do |tc, value|
tc.record_change(field[:name], tc.topic.send(field[:name]), value)
tc.topic.send("#{field[:name]}=".to_sym, value.present? ? value : nil)
end
add_to_serializer(:topic_view, field[:name].to_sym) do
object.topic.send(field[:name])
end
add_preloaded_topic_list_custom_field(field[:name])
# Serialize to the topic list
add_to_serializer(:topic_list_item, field[:name].to_sym) do
object.send(field[:name])
end
end
end
Initializer.js
import { withPluginApi } from 'discourse/lib/plugin-api';
import discourseComputed from "discourse-common/utils/decorators";
import { alias } from '@ember/object/computed';
import { isDefined, fieldInputTypes } from '../lib/topic-custom-field';
export default {
name: "topic-custom-field-intializer",
initialize(container) {
const CUSTOM_FIELDS = [
{ name: "isClassifiedListing", type: "boolean" },
{ name: "listingStatus", type: "string" },
{ name: "listingDetails", type: "json" },
];
CUSTOM_FIELDS.forEach((field) => {
withPluginApi('0.11.2', api => {
api.registerConnectorClass('composer-fields', 'composer-topic-custom-field-container', {
setupComponent(attrs, component) {
const model = attrs.model;
if (!isDefined(model[field.name]) && model.topic && model.topic[field.name]) {
model.set(field.name, model.topic[field.name]);
}
let props = {
fieldName: field.name,
fieldValue: model.get(field.name)
}
component.setProperties(Object.assign(props, fieldInputTypes(field.type)));
},
actions: {
onChangeField(fieldValue) {
this.set(`model.${field.name}`, fieldValue);
}
}
});
api.registerConnectorClass('edit-topic', 'edit-topic-custom-field-container', {
setupComponent(attrs, component) {
const model = attrs.model;
let props = {
fieldName: field.name,
fieldValue: model.get(field.name)
}
component.setProperties(Object.assign(props, fieldInputTypes(field.type)));
},
actions: {
onChangeField(fieldValue) {
this.set(`buffered.${field.name}`, fieldValue);
}
}
});
api.serializeOnCreate(field.name);
api.serializeToDraft(field.name);
api.serializeToTopic(field.name, `topic.${field.name}`);
api.registerConnectorClass('topic-title', 'topic-title-custom-field-container', {
setupComponent(attrs, component) {
const model = attrs.model;
const controller = container.lookup('controller:topic');
component.setProperties({
fieldName: field.name,
fieldValue: model.get(field.name),
showField: !controller.get('editingTopic') && isDefined(model.get(field.name))
});
controller.addObserver('editingTopic', () => {
if (this._state === 'destroying') return;
component.set('showField', !controller.get('editingTopic') && isDefined(model.get(field.name)));
});
model.addObserver(field.name, () => {
if (this._state === 'destroying') return;
component.set('fieldValue', model.get(field.name));
});
}
});
api.modifyClass('component:topic-list-item', {
customFieldName: field.name,
customFieldValue: alias(`topic.${field.name}`),
@discourseComputed('customFieldValue')
showCustomField: (value) => (isDefined(value))
});
});
});
}
}