【发布时间】:2021-07-18 22:48:48
【问题描述】:
程序和版本
您好,我正在使用 Rails 6.1.3.2、Bootstrap 5.0.1、Ruby 2.6.5、Haml 5.2.1 和 Webpack 4.46.0 开展个人 Rails 项目。
目标
我正在尝试在用户第一次访问特定页面时在页面加载时进行模式显示,之后他们必须单击一个按钮才能再次查看它。
方法
我正在使用 Bootstrap 提供的 Javascript function 来显示模式,除了在 application.js 文件中需要它之外,这还需要我将“bootstrap”作为 Webpack 的变量提供。我在 User 模型上有一个属性,用于跟踪他们是否访问过该页面,如果该属性为 false,则加载 javascript_pack_tag 的 if 语句。
问题
该功能有效,但关闭模式后,下拉链接不打开,手风琴会打开但不关闭。如果我从 application.js 中删除 require("bootstrap"),第一次一切正常,但是当页面重新加载时,所有 Javascript 都停止工作。
我的怀疑和以前的努力
我怀疑当包含javascript_pack_tag 时,Bootstrap 会被加载两次并导致异常问题。我尝试在 research_topics.js 文件中使用 import 语句,但出现了同样的问题。我尝试从 application.js 中删除 require("bootstrap"),这适用于页面的初始访问,但是一旦重新加载页面,Bootstrap 组件就不再工作了。我在 Rails 版本 4 上学习过,所以我是 Webpack 的新手,可能会忽略一些简单的东西。任何帮助将不胜感激。
我的代码
完整项目可在here 获得。只需运行 bundle install、rails db:migrate 和 rails db:seed 即可进行设置。
app/views/research_topics/index.html.haml
= javascript_pack_tag 'research_topics_index', 'data-turbolinks-track': 'reload' if !current_user.visited_research_topics
%h1.mx-auto.text-center.mt-3= "Research Topics"
.container-md.mx-auto.p-0
%button.mb-3.fs-5.btn.btn-primary{data: { bs: { toggle: "modal", target: "#addTopicModal" } } }= "Add Topic"
.modal#addTopicModal{ tabindex: "-1", aria: { labelledby: "topicModalLabel", hidden: "true" } }
.modal-dialog
.modal-content
.modal-header
%h5.modal-title#topicModalLabel= "New Topic"
%button.btn-close{ type: "button", data: { bs: { dismiss: "modal" } }, aria: { label: "Close" } }
.modal-body
= form_for ResearchTopic.new do |f|
.mb-3
= f.label :title, class: "form-label"
= f.text_field :title, class: "form-control mb-3"
= f.label :search_terms, "Search Terms (add up to 5)", class: "form-label"
- 5.times do |n|
= f.text_field :search_terms, value: "", id: "searchTerm#{n}", name: "research_topic[search_terms][]", class: "form-control mb-2"
= f.submit "Add", class: "btn btn-primary"
- current_user.research_topics.each.with_index do |topic, topic_number|
.container.mb-3.px-0.py-3.border-top.border-dark.border-3
.modal{id: "topic-#{topic_number}-SearchTermModal", tabindex: "-1", aria: { labelledby: "searchTermModalLabel", hidden: "true" } }
.modal-dialog
.modal-content
.modal-header
%h5.modal-title#searchTermModalLabel= "New Search Term"
%button.btn-close{ data: { bs: { dismiss: "modal" } }, aria: { label: "Close" } }
.modal-body
= form_for SearchTerm.new do |f|
.mb-3
= f.label :term, "New Term For #{topic.title}", class: "form-label"
= f.text_field :term, class: "form-control mb-3"
= f.hidden_field :research_topic_id, value: topic.id
= f.submit "Add", class: "btn btn-primary"
%h2= topic.title
.row
.col-auto
%h4= "Search Terms:"
.col-9
.row.gy-2
- topic.search_terms.each do |term|
.col-auto
= form_for term, method: :delete do |f|
%p.fs-5.text-dark
= term.term
%button.btn-close(type="submit" aria-label="Close")
.col-auto
%button.btn.btn-primary{ data: { bs: { toggle: "modal", target: "#topic-#{topic_number}-SearchTermModal" } } }= "Add Term"
- if topic.research_articles.length == 0
%h4.p-3.my-3.bg-secondary= "There were no articles found for your search."
- else
.accordion.my-3.bg-light{ id: "topic-#{topic_number}-articlesAccordion" }
.accordion-item
%h2.accordion-header{ id: "topic-#{topic_number}-new" }
%button.accordion-button.collapsed{ type: "button", data: { bs: { toggle: "collapse", target: "#topic-#{topic_number}-newArticlesCollapse" } }, aria: { expanded: "false", controls: "topic-#{topic_number}-newArticlesCollapse" } }
= "New"
%span.badge.bg-primary.ms-3= topic.research_articles.where(status: "new").length
- if topic.new_today_count > 0
%span.ms-3.text-success= "#{topic.new_today_count} New Today"
.collapse.accordion-collapse{ id: "topic-#{topic_number}-newArticlesCollapse" , aria: { labelledby: "topic-#{topic_number}-new" } }
.accordion-body
.accordion{ id: "topic-#{topic_number}-newAccordion" }
- if topic.research_articles.where(status: "new").length == 0
%p= "It looks like there aren't any articles you haven't seen before. Try adding a new search term for more results."
- topic.research_articles.where(status: "new").each.with_index do |article, article_number|
.accordion-item
%h2.accordion-header{ id: "topic-#{topic_number}-newArticle-#{article_number}" }
%button.accordion-button.collapsed{ type: "button", data: { bs: { toggle: "collapse", target: "#topic-#{topic_number}-newArticle-#{article_number}-collapse" } }, aria: { expanded: "false", controls: "topic-#{topic_number}-newArticle-#{article_number}-collapse" } }
.container
.row= article.title
.row.mt-3.text-muted= article.article_published
.collapse.accordion-collapse{ id: "topic-#{topic_number}-newArticle-#{article_number}-collapse", aria: { labelledby: "topic-#{topic_number}-newArticle-#{article_number}" } }
.accordion-body
= render 'shared/research_article', article: article
.accordion-item
%h2.accordion-header{ id: "topic-#{topic_number}-saved" }
%button.accordion-button.collapsed{ type: "button", data: { bs: { toggle: "collapse", target: "#topic-#{topic_number}-savedArticlesCollapse" } }, aria: { expanded: "false", controls: "topic-#{topic_number}-savedArticlesCollapse" } }
= "Saved"
%span.badge.bg-primary.ms-3= topic.research_articles.where(status: "saved").length
.collapse.accordion-collapse{ id: "topic-#{topic_number}-savedArticlesCollapse", aria: { labelledby: "topic-#{topic_number}-saved" } }
.accordion-body
.accordion.bg-light{ id: "topic-#{topic_number}-savedAccordion" }
- topic.research_articles.where(status: "saved").each.with_index do |article, article_number|
.accordion-item
%h2.accordion-header{ id: "topic-#{topic_number}-savedArticle-#{article_number}" }
%button.accordion-button.collapsed{ type: "button", data: { bs: { toggle: "collapse", target: "#topic-#{topic_number}-savedArticle-#{article_number}-collapse" } }, aria: { expanded: "false", controls: "topic-#{topic_number}-savedArticle-#{article_number}-collapse" } }
.container
.row= article.title
.row.mt-3.text-muted= article.article_published
.collapse.accordion-collapse{ id: "topic-#{topic_number}-savedArticle-#{article_number}-collapse", aria: { labelledby: "topic-#{topic_number}-savedArticle-#{article_number}" } }
.accordion-body
= render 'shared/research_article', article: article
.accordion-item
%h2.accordion-header{ id: "topic-#{topic_number}-read" }
%button.accordion-button.collapsed{ type: "button", data: { bs: { toggle: "collapse", target: "#topic-#{topic_number}-readArticlesCollapse" } }, aria: { expanded: "false", controls: "topic-#{topic_number}-readArticlesCollapse" } }
= "Read"
%span.ms-3.badge.bg-primary= topic.research_articles.where(status: "read").length
.collapse.accordion-collapse{ id: "topic-#{topic_number}-readArticlesCollapse", aria: { labelledby: "topic-#{topic_number}-read" } }
.accordion-body
.accordion{ id: "topic-#{topic_number}-readAccordion" }
- topic.research_articles.where(status: "read").each.with_index do |article, article_number|
.accordion-item
%h2.accordion-header{ id: "topic-#{topic_number}-readArticle-#{article_number}" }
%button.accordion-button.collapsed{ type: "button", data: { bs: { toggle: "collapse", target: "#topic-#{topic_number}-readArticle-#{article_number}-collapse" } }, aria: { expanded: "false", controls: "topic-#{topic_number}-readArticle-#{article_number}-collapse" } }
.container
.row= article.title
.row.mt-3.text-muted= article.article_published
.collapse.accordion-collapse{ id: "topic-#{topic_number}-readArticle-#{article_number}-collapse", aria: { labelledby: "topic-#{topic_number}-readArticle-#{article_number}" } }
.accordion-body
= render 'shared/research_article', article: article
%button.btn.btn-dark{type: "button", data: { bs: { toggle: "modal", target: "#deleteTopic-#{topic_number}" } } }= "Delete Topic"
.modal{ id: "deleteTopic-#{topic_number}", tabindex: "-1" }
.modal-dialog
.modal-content
.modal-body
%p= "Are you sure you want to delete the topic <em>#{topic.title}</em>? This cannot be undone.".html_safe
.row
.col-2
= form_for topic, method: :delete do |f|
= f.submit "Yes", class: "btn btn-dark"
.col-2
%button.btn.btn-dark{ data: { bs: { dismiss: "modal" } } }= "No"
.modal#infoModal{ tabindex: "-1", aria: { labelledby: "infoModalLabel", hidden: "false" } }
.modal-dialog.modal-lg
.modal-content
.modal-header
.modal-title.h4.text-dark#infoModalLabel= "About Research Topics Page"
%button.btn-close{ type: "button", data: { bs: { dismiss: "modal" } }, aria: { label: "Close" } }
.modal-body
%p.fs-5.mb-3.text-dark= "- On this page you can add as many research topics as you like."
%p.fs-5.mb-3.text-dark= "- Every 24 hours, the arXiv API is queried with the search terms you provide."
%p.fs-5.mb-3.text-dark= "- arXiv contains nearly 2 million scholarly articles in various academic fields."
%p.fs-5.mb-3.text-dark= "- The 10 most recent articles will appear in the 'new' section of each topic every day."
%p.fs-5.mb-3.text-dark= "- The 'new' section is automatically refreshed each time you add or delete a search term."
%p.fs-5.mb-3.text-dark= "- You can save the articles for later, mark them as read or not interested, or take notes about them."
%p.fs-5.mb-3.text-dark= "- If you see older articles appearing in the 'new' section, then you have read or saved all of the newest articles and the algorithm is finding older ones so there is always something you haven't seen before."
%p.fs-5.mb-3.text-dark= "- Click the <i class='bi bi-question-circle mx-2 h4'></i> to see this message again.".html_safe
app/javascript/packs/application.js
// This file is automatically compiled by Webpack, along with any other files
// present in this directory. You're encouraged to place your actual application logic in
// a relevant structure within app/javascript and only use these pack files to reference
// that code so it'll be compiled.
import Rails from "@rails/ujs"
import Turbolinks from "turbolinks"
import * as ActiveStorage from "@rails/activestorage"
import "channels"
import '../stylesheets/application'
require("bootstrap")
import 'bootstrap-icons/font/bootstrap-icons.css'
Rails.start()
Turbolinks.start()
ActiveStorage.start()
app/javascript/packs/research_topics_index.js
$(window).on('load', function() {
new bootstrap.Modal($('#infoModal')).show();
});
config/webpack/environment.js
const webpack = require('webpack');
const { environment } = require('@rails/webpacker')
environment.plugins.append(
'Provide',
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
Popper: ['popper.js', 'default'],
bootstrap: 'bootstrap'
})
)
module.exports = environment
【问题讨论】:
标签: ruby-on-rails webpack bootstrap-5