提问人:jamesc 提问时间:10/29/2023 最后编辑:jamesc 更新时间:10/30/2023 访问量:60
无法将数据结构从 Rails 7 传递给 javascript 函数
Trouble passing a data structure from Rails 7 to a javascript function
问:
我需要在 data-tinymce html 标签中保留结构以传递给 javascript 函数,但该结构不知何故没有被保留,这导致 javascript 函数中的方法失败。
结构是
{
event_root: null,
selector: ".tinymce",
menubar: "file edit view insert format tools table help",
toolbar: ["undo redo | blocks fontfamily fontsize | bold italic underline strikethrough | align numlist bullist","link image | accordion accordionremove | table media | lineheight outdent indent| forecolor backcolor removeformat charmap emoticons code fullscreen preview save print | pagebreak codesample | ltr rtl"],
toolbar_mode: "sliding",
contextmenu: "link image table",
quickbars_selection_toolbar: "bold italic | quicklink h2 h3 blockquote quickimage quicktable",
plugins: "preview importcss searchreplace autolink autosave save directionality code,visualblocks visualchars fullscreen image link media codesample,table charmap pagebreak nonbreaking insertdatetime advlist lists,wordcount help charmap quickbars emoticons accordion",
promotion: false,
autosave_ask_before_unload: true,
autosave_interval: "30s",
autosave_prefix: "tinymce-autosave-{path}{query}-{id}-",
autosave_restore_when_empty: true,
autosave_retention: "30m",
image_caption: true,
image_advtab: true,
image_class_list: [{"title":"None","value":""},{"title":"Drop shadow","value":"shadow"}]
}
我有一个链接,该链接是由一个辅助函数生成的,该函数通过 data-tinymce html atrtribute 传递此结构,代码如下
# This method creates a link with `data-id` `data-fields` attributes. These attributes are used to create new instances of the nested fields through Javascript.
def link_to_add_fields(name, f, association)
new_object = f.object.send(association).klass.new
# Saves the unique ID of the object into a variable.
# This is needed to ensure the key of the associated array is unique. This is makes parsing the content in the `data-fields` attribute easier through Javascript.
# We could use another method to achive this.
id = new_object.object_id
#tinymce_config = tinymce :try
tinymce = CcsCms::CustomPage::ConfigTinymce.get_tiny_config_for_js("try")
#tinymce = "<%=tinymce(:try)%>"
# https://api.rubyonrails.org/ fields_for(record_name, record_object = nil, fields_options = {}, &block)
# record_name = :page_sections
# record_object = new_object
# fields_options = { child_index: id }
# child_index` is used to ensure the key of the associated array is unique, and that it matched the value in the `data-id` attribute.
# `page[page_sections_attributes][child_index_value][_destroy]`
fields = f.fields_for(association, new_object, child_index: id) do |builder|
# `association.to_s.singularize + "_fields"` ends up evaluating to `page_sections_fields`
# The render function will then look for `views/pages/_page_sections_fields.html.erb`
# The render function also needs to be passed the value of 'builder', because `views/pages/_page_sections_fields.html.erb` needs this to render the form tags.
render(association.to_s.singularize + "_fields", form: builder)
end
# This renders a simple link, but passes information into `data` attributes.
# This info can be named anything we want, but in this case we chose `data-id:` and `data-fields:`.
# The `id:` is from `new_object.object_id`.
# The `fields:` are rendered from the `fields` blocks.
# We use `gsub("\n", "")` to remove anywhite space from the rendered partial.
# The `id:` value needs to match the value used in `child_index: id`.
link_to(
name,
"#",
class: "add_fields",
data: {
tinymce: tinymce, #.to_json.html_safe,
id: id,
fields: fields.gsub("\n", ""),
},
)
end
此链接生成的 html 是
<a class="add_fields" data-tinymce="{
event_root: null,
selector: ".tinymce",
menubar: "file edit view insert format tools table help",
toolbar: ["undo redo | blocks fontfamily fontsize | bold italic underline strikethrough | align numlist bullist","link image | accordion accordionremove | table media | lineheight outdent indent| forecolor backcolor removeformat charmap emoticons code fullscreen preview save print | pagebreak codesample | ltr rtl"],
toolbar_mode: "sliding",
contextmenu: "link image table",
quickbars_selection_toolbar: "bold italic | quicklink h2 h3 blockquote quickimage quicktable",
plugins: "preview importcss searchreplace autolink autosave save directionality code,visualblocks visualchars fullscreen image link media codesample,table charmap pagebreak nonbreaking insertdatetime advlist lists,wordcount help charmap quickbars emoticons accordion",
promotion: false,
autosave_ask_before_unload: true,
autosave_interval: "30s",
autosave_prefix: "tinymce-autosave-{path}{query}-{id}-",
autosave_restore_when_empty: true,
autosave_retention: "30m",
image_caption: true,
image_advtab: true,
image_class_list: [{"title":"None","value":""},{"title":"Drop shadow","value":"shadow"}]
}" data-id="34920" data-fields="<div class="page-section"> <p></p> <section> <fieldset> <legend> Page Section </legend> <input autocomplete="off" type="hidden" value="false" name="menu_item[page_sections_attributes][34920][_destroy]" id="menu_item_page_sections_attributes_34920__destroy" /> <div class="cms-admin-field"> <label for="menu_item_page_sections_attributes_34920_content">Content</label>: <textarea class="tinymce" name="menu_item[page_sections_attributes][34920][content]" id="menu_item_page_sections_attributes_34920_content"></textarea> </div> <script>//<![CDATA[TinyMCERails.initialize('try', { });//]]></script> <div class="cms-admin-field"> <label for="menu_item_page_sections_attributes_34920_collapsed_header_text">Collapsed header text</label>: <input editor="template classic type classic" type="text" value="" name="menu_item[page_sections_attributes][34920][collapsed_header_text]" id="menu_item_page_sections_attributes_34920_collapsed_header_text" /> </div> <div class="cms-admin-field"> <label for="menu_item_page_sections_attributes_34920_include_contact_form">Include contact form</label>: <input name="menu_item[page_sections_attributes][34920][include_contact_form]" type="hidden" value="0" autocomplete="off" /><input type="checkbox" value="1" name="menu_item[page_sections_attributes][34920][include_contact_form]" id="menu_item_page_sections_attributes_34920_include_contact_form" /> </div> <div class="cms-admin-field"> <label for="menu_item_page_sections_attributes_34920_collapsible">Collapsible</label>: <input name="menu_item[page_sections_attributes][34920][collapsible]" type="hidden" value="0" autocomplete="off" /><input type="checkbox" value="1" name="menu_item[page_sections_attributes][34920][collapsible]" id="menu_item_page_sections_attributes_34920_collapsible" /> </div> <div class="cms-admin-field"> <label for="menu_item_page_sections_attributes_34920_has_borders">Has borders</label>: <input name="menu_item[page_sections_attributes][34920][has_borders]" type="hidden" value="0" autocomplete="off" /><input type="checkbox" value="1" name="menu_item[page_sections_attributes][34920][has_borders]" id="menu_item_page_sections_attributes_34920_has_borders" /> </div> <div class="cms-admin-field"> <label for="menu_item_page_sections_attributes_34920_full_width">Full width</label>: <input name="menu_item[page_sections_attributes][34920][full_width]" type="hidden" value="0" autocomplete="off" /><input type="checkbox" value="1" name="menu_item[page_sections_attributes][34920][full_width]" id="menu_item_page_sections_attributes_34920_full_width" /> </div> <div> <a class="remove_fields" href="#">Remove</a> </div> </fieldset> </section></div>" href="#">Add Section</a>
点击链接时摩擦的javascript代码如下
handleClick(link, e) {
// Stop the function from executing if a link or event were not passed into the function.
if (!link || !e) return;
// Prevent the browser from following the URL.
e.preventDefault();
//get the tinymce config data
let config = link.dataset.tinymce;
// Save a unique timestamp to ensure the key of the associated array is unique.
let time = new Date().getTime();
// Save the data id attribute into a variable. This corresponds to `new_object.object_id`.
let linkId = link.dataset.id;
// Create a new regular expression needed to find any instance of the `new_object.object_id` used in the fields data attribute if there's a value in `linkId`.
let regexp = linkId ? new RegExp(linkId, "g") : null;
// Replace all instances of the `new_object.object_id` with `time`, and save markup into a variable if there's a value in `regexp`.
let newFields = regexp ? link.dataset.fields.replace(regexp, time) : null;
// Add the new markup to the form if there are fields to add.
newFields ? link.insertAdjacentHTML("beforebegin", newFields) : null;
console.log(config);
// tinymce.init(config);
tinymce.init(
{
event_root: null,
selector: ".tinymce",
menubar: "file edit view insert format tools table help",
toolbar: ["undo redo | blocks fontfamily fontsize | bold italic underline strikethrough | align numlist bullist","link image | accordion accordionremove | table media | lineheight outdent indent| forecolor backcolor removeformat charmap emoticons code fullscreen preview save print | pagebreak codesample | ltr rtl"],
toolbar_mode: "sliding",
contextmenu: "link image table",
quickbars_selection_toolbar: "bold italic | quicklink h2 h3 blockquote quickimage quicktable",
plugins: "preview importcss searchreplace autolink autosave save directionality code,visualblocks visualchars fullscreen image link media codesample,table charmap pagebreak nonbreaking insertdatetime advlist lists,wordcount help charmap quickbars emoticons accordion",
promotion: false,
autosave_ask_before_unload: true,
autosave_interval: "30s",
autosave_prefix: "tinymce-autosave-{path}{query}-{id}-",
autosave_restore_when_empty: true,
autosave_retention: "30m",
image_caption: true,
image_advtab: true,
image_class_list: [{"title":"None","value":""},{"title":"Drop shadow","value":"shadow"}]
}
);
};
调用似乎显示正确的结构,如下所示console.log(config);
{
event_root: null,
selector: ".tinymce",
menubar: "file edit view insert format tools table help",
toolbar: ["undo redo | blocks fontfamily fontsize | bold italic underline strikethrough | align numlist bullist","link image | accordion accordionremove | table media | lineheight outdent indent| forecolor backcolor removeformat charmap emoticons code fullscreen preview save print | pagebreak codesample | ltr rtl"],
toolbar_mode: "sliding",
contextmenu: "link image table",
quickbars_selection_toolbar: "bold italic | quicklink h2 h3 blockquote quickimage quicktable",
plugins: "preview importcss searchreplace autolink autosave save directionality code,visualblocks visualchars fullscreen image link media codesample,table charmap pagebreak nonbreaking insertdatetime advlist lists,wordcount help charmap quickbars emoticons accordion",
promotion: false,
autosave_ask_before_unload: true,
autosave_interval: "30s",
autosave_prefix: "tinymce-autosave-{path}{query}-{id}-",
autosave_restore_when_empty: true,
autosave_retention: "30m",
image_caption: true,
image_advtab: true,
image_class_list: [{"title":"None","value":""},{"title":"Drop shadow","value":"shadow"}]
}
如果我从控制台复制并粘贴此结构并将其作为参数放置到调用中,则调用将按预期完美工作,但是当我用配置变量替换参数时,该函数不起作用。tinymce.init
我在助手中尝试了to_json、html_safe和原始方法
答:
1赞
Alex
10/30/2023
#1
你肯定需要在这里使用。 是一个字符串,当您从 读取它时,它不会转换为 json。你必须这样做:to_json
data-tinymce
dataset
JSON.parse
<%
config = {
event_root: nil,
selector: ".tinymce",
menubar: "file edit view insert format tools table help",
toolbar: ["undo redo | blocks fontfamily fontsize | bold italic underline strikethrough | align numlist bullist","link image | accordion accordionremove | table media | lineheight outdent indent| forecolor backcolor removeformat charmap emoticons code fullscreen preview save print | pagebreak codesample | ltr rtl"],
toolbar_mode: "sliding",
contextmenu: "link image table",
quickbars_selection_toolbar: "bold italic | quicklink h2 h3 blockquote quickimage quicktable",
plugins: "preview importcss searchreplace autolink autosave save directionality code,visualblocks visualchars fullscreen image link media codesample,table charmap pagebreak nonbreaking insertdatetime advlist lists,wordcount help charmap quickbars emoticons accordion",
promotion: false,
autosave_ask_before_unload: true,
autosave_interval: "30s",
autosave_prefix: "tinymce-autosave-{path}{query}-{id}-",
autosave_restore_when_empty: true,
autosave_retention: "30m",
image_caption: true,
image_advtab: true,
image_class_list: [{"title":"None","value":""},{"title":"Drop shadow","value":"shadow"}]
}
%>
<a class="add_fields" data-tinymce="<%= config.to_json %>" href="#">Add Section</a>
<script charset="utf-8">
var config = JSON.parse(document.querySelector(".add_fields").dataset.tinymce)
console.log(config)
</script>
评论
0赞
jamesc
10/30/2023
谢谢,但我就是无法让它工作。您的解决方案有效并保护了我缺少的步骤,但是从 yml 文件中获取数据并解析 Tinymce 配置是所有问题的地方,虽然它似乎给了我与硬编码结构相同的结果,但我最终在控制台中得到了一个对象。我已经受够了为此扯头发,我将重新考虑我的方法,因为我花了数周时间解决这个问题,而解决方案实际上只需要十分钟,授权真的不应该这么困难,我显然有问题。
1赞
Alex
10/30/2023
发布了一个关于您上一个问题的工作示例
评论
data-tinymce