【问题标题】:Rendering dynamic scss-files with ajax, rails使用 ajax、rails 渲染动态 scss 文件
【发布时间】:2013-10-23 00:16:08
【问题描述】:

正如标题所示,我的主要目标是在 ajax 调用之后呈现动态 scss(.erb) 文件。

assets/javascripts/header.js

// onChange of a checkbox, a database boolean field should be toggled via AJAX
$( document ).ready(function() {
  $('input[class=collection_cb]').change(function() {

    // get the id of the item
    var collection_id = $(this).parent().attr("data-collection-id");
    // show a loading animation
    $("#coll-loading").removeClass("vhidden");

    // AJAX call
    $.ajax({
      type    : 'PUT',
      url      : "/collections/" + collection_id + "/toggle",
      success : function() {
        // removal of loading animation, a bit delayed, as it would be too fast otherwise
        setTimeout(function() {
          $("#coll_loading").addClass("vhidden");
        }, 300);
      },
    });
  });
});

controller/collections_controller.rb

def toggle
  # safety measure to check if the user changes his collection
  if current_user.id == Collection.find(params[:id]).user_id
    collection = Collection.find(params[:id])

    # toggle the collection
    collection.toggle! :auto_add_item
  else
    # redirect the user to error page, alert page
  end

  render :nothing => true
end

当我单独切换数据库对象时,一切都非常顺利。

现在我想添加一些额外的香料,并根据用户当前选择的集合更改我的 50+ li's 的 CSS。

我的 desired CSS 看起来像这样,它检查 li 元素是否属于集合,如果属于,则给它们一个边框颜色。

ul#list > li[data-collections~='8'][data-collections~='2']
{
  border-color: #ff2900;
}

我将此添加到我的控制器以生成 []-conditions:

def toggle
  # .
  # .
  # toggle function

  # return the currently selected collection ids in the [data-collections]-format
  @active_collections = ""
  c_ids = current_user.collections.where(:auto_add_item => true).pluck('collections.id')
  if c_ids.size != 0
    c_ids.each { |id| @active_collections += "[data-collections~='#{id}']" }
  end

  # this is what gets retrieved
  # @active_collections => [data-collections~='8'][data-collections~='2']
end

现在我需要一种方法将这些括号放入动态生成的 scss 文件中。

我尝试添加:

respond_to do |format|
  format.css
end

到我的控制器,拥有文件 views/collections/toggle.css.erb

ul#list<%= raw active_collections %> > li<%= raw active_collections %> {
  border-color: #ff2900;
}

它不起作用,另一种方法是从我的控制器渲染 css 文件,然后将其传递给 Manuel Meurer 所描述的视图

我弄乱了文件名吗?喜欢使用css 而不是scss?你有什么想法我应该如何进行吗?

感谢您的帮助!

为什么选择动态 CSS? - 推理

我知道这通常应该通过 JavaScript 添加类来实现。我为什么需要动态 css 的原因是,当用户决定更改选定的集合时,他会非常专注。比如 3 秒内打 4 个电话,然后暂停 5 分钟,然后在 4 秒内打 5 个电话。每次调用后,JavaScript 将花费太长时间来循环遍历 50+ li's

更新

事实证明,JavaScript 在处理我的“长”列表方面非常快...感谢大家指出我的想法中的错误!

【问题讨论】:

  • 我不明白为什么需要动态 CSS。为什么不使用静态 CSS 并通过 jQuery 切换 div 的类,这很简单。
  • 如果您想加载动态 CSS 文件,我认为您必须使用 javascript 将 &lt;link rel&gt; 元素附加到您的 HTML 页面。但正如@BillyChan 所说,没有必要走那么远……如果你想根据特定条件应用样式,那么使用 javascript。如果该样式将应用于多个元素,则将该样式插入页面的 head 元素。
  • 感谢您的输入,我通常会站在您这边,为什么我想使用 CSS 而不是 JavaScript 是因为我的 ul 可以有 50+ li's。在每一个小开关之后都通过它们会使我的应用程序超级慢......
  • 在 JS 中循环 50 个元素不会那么慢,至少不会比另一个 HTTP 请求慢。
  • 嗯,谢谢,我再试试 JS 的解决方案,可能是我上次搞砸了,我明天给大家看看结果

标签: ruby-on-rails ajax ruby-on-rails-3 dynamic sass


【解决方案1】:

在我看来,您遇到的问题与 CSS 无关。这与您的系统如何工作有关

CSS 是静态加载的(来自 http 请求),这意味着当页面呈现时,如果您更改服务器上的 CSS 文件,它将不会更新

JS 是客户端,旨在与呈现的 HTML 元素交互(通过 DOM)。这意味着 JS 本质上是动态的,这就是为什么我们可以将它与 Ajax 等技术一起使用来更改页面的某些部分

这就是我认为您的问题所在......

您的 JS 调用没有重新加载页面,这意味着 CSS 保持静态。目前没有办法重新加载 CSS 并让它们在不刷新的情况下呈现(发送 HTTP 请求)。这意味着您对 JS 所做的任何更新都必须包含每个加载的 CSS

根据您的 OP 的 cmets,您应该真正考虑更新列表元素的类。如果你使用这样的东西,它应该可以立即工作:

$('li').addClass('new');

希望这有帮助吗?

【讨论】:

  • 嘿,丰富!我真的很感谢你的帮助!事实证明,我的系统/我的想法有问题。我找到了一个很好的 JS 解决方案,它可以像预期的那样完美运行! :) 我真的必须在你和比利之间掷骰子,谁会得到赏金......
  • 这个工具选择了你,明智地使用我的代表^^,miniwebtool.com/random-name-picker
  • 嘿伙计,谢谢您的代表!哈哈不错的选择!我会看看我是否可以为比利的问题设置赏金
【解决方案2】:

如果我对你的功能理解正确的话,其实你所需要的都可以通过 JavaScript 简单地实现,不需要任何 hack。

让我先整理一下你的功能

  • 给定访问页面的用户
  • 当他选中一个复选框时
  • 他会看到一个加载标志,这意味着这是与服务器的交互
  • 当装载标志停止时
  • 他会看到他检查的行(或“li”)有一个边框,这意味着他的操作已被服务器接受

然后是解决方案。 为了便于阅读,我将简化您将符号代码加载到命名函数而不是实际代码中。

$(document).ready(function() {
  $('input[class=collection_cb]').change(function() {

    // Use a variable to store parent of current scope for using later
    var $parent = $(this).parent();

    // get the id of the item
    var collection_id = $parent.attr("data-collection-id");

    show_loading_sign();

    // AJAX call
    $.ajax({
      type    : 'PUT',
      url      : "/collections/" + collection_id + "/toggle",
      success : function() {
        // This is the effect you need.
        $parent.addClass('green_color_border');
      },
      error: function() {
        $parent.addClass('red_color_border');
      },
      complete: function() {
        close_loading_sign(); /*Close the sign no matter success or error*/
      } 
    });
  });
});

让我知道我对功能的理解是否正确以及这是否可以解决问题。

【讨论】:

    【解决方案3】:

    如果当用户切换集合选择时,您使用 jquery 更改 ul 上的 one 类,然后基于该类定义静态样式?

    例如,您的原始标记可能是:

    ul#list.no_selection
      li.collection8.collection2
      li.collection1
    

    你的 css 会静态地:

    ul.collection1 li.collection1,
    ul.collection2 li.collection2,
    ...
    ul.collection8 li.collection8 {
      border-color: #ff2900;
    }
    

    所以默认情况下,不会有边框。但是如果用户选择集合 8,你的 jquery 会这样做:

    $('ul#list').addClass('collection8')
    

    瞧,在collection8 中的li 周围加边框--无需在javascript 中循环所有lis,也无需动态加载样式表。

    您认为,这对您的情况有用吗?

    【讨论】:

    • 感谢 Carol 的帮助,这是聪明的想法 :) 静态 CSS 对我不起作用,因为 li 可以有许多不同的集合。
    猜你喜欢
    • 2017-08-29
    • 1970-01-01
    • 2012-02-28
    • 2018-02-24
    • 2018-01-19
    • 1970-01-01
    • 2018-04-17
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多