使用ajax,rails渲染动态scss文件

时间:2013-10-15 08:56:27

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

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

资产/ Javascript角/ 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);
      },
    });
  });
});

控制器/ 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相应地更改为当前选定的用户集合。

我的所需的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处理我的“长”列表非常快......谢谢你们指出我的想法中的错误!

3 个答案:

答案 0 :(得分:1)

如果我正确理解了您的功能,实际上您只需通过JavaScript即可实现所有功能,无需任何黑客攻击。

让我先介绍一下你的功能

  • 鉴于用户访问该页面
  • 检查复选框时
  • 他会看到一个加载标志,暗示这是与服务器的交互
  • 加载标志停止时
  • 他会看到他检查的行(或“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*/
      } 
    });
  });
});

如果我对功能的理解是正确的,以及这是否可以解决问题,请告诉我。

答案 1 :(得分:1)

在我看来,你遇到的问题与CSS没有关系;它与你的系统如何工作有关

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

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

这就是我认为你的问题出现的地方......

你的JS调用没有重新加载页面,这意味着CSS保持静态。目前没有办法重新加载CSS并让它们渲染而不刷新(发送HTTP请求)。这意味着您使用JS进行的任何更新都必须包含每个加载的CSS

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

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

希望这有帮助吗?

答案 2 :(得分:0)

当用户切换集合选择时,如果在ul上使用jquery更改一个类,然后根据该类定义静态样式,该怎么办?

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

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')

并且在li内的collection8边框 - 没有循环遍历javascript中的所有li并且没有动态加载样式表。

你怎么看?这会对你的情况有用吗?