【问题标题】:How to make Javascript generated checkboxes persist?如何使 Javascript 生成的复选框持续存在?
【发布时间】:2015-07-22 16:36:29
【问题描述】:

脚本中的“ajax”向服务器发送一条发布或删除消息。包含 ajax 的 javascript 是添加复选框的内容。我们如何使创建的复选框元素持久化,以便当用户刷新页面时它们仍然存在?

习惯/_form.html.erb

<label id="<%= @habit.id %>" class="habit-id"> Missed: </label>
<% @habit.levels.each_with_index do |level, index| %>
  <% if @habit.current_level >= (index + 1) %>
    <p>
      <label id="<%= level.id %>" class="level-id"> Level <%= index + 1 %>: </label>
      <%= check_box_tag nil, true, level.missed_days > 0, {class: "habit-check"} %>
      <%= check_box_tag nil, true, level.missed_days > 1, {class: "habit-check"} %>
      <%= check_box_tag nil, true, level.missed_days > 2, {class: "habit-check"} %>
   </p>
  <% end %>
<% end %>

habit.js

$(document).ready(function() {
  var handleChange = function() {
    habit = $(this).parent().prev().attr("id");
    level = $('label', $(this).parent()).attr("id");
    if ($(this).is(":checked")) {
      $.ajax({
        url: "/habits/" + habit + "/levels/" + level + "/days_missed",
        method: "POST"
      });
    } else {
      $.ajax({
        url: "/habits/" + habit + "/levels/" + level + "/days_missed/1",
        method: "DELETE"
      });
    }
    if (!$('input[type="checkbox"]:not(:checked)', $(this).parent()).length) {
      /* this is just an example, you will have to ammend this */
      $(this).parent().append($('<input type="checkbox" class="habit-check">'));
      $(this).parent().append($('<input type="checkbox" class="habit-check">'));
      $(this).parent().append($('<input type="checkbox" class="habit-check">'));
      $(".habit-check").on('change',handleChange);
    }
  }
  $(".habit-check").on('change',handleChange);
});

habit.rb

class Habit < ActiveRecord::Base
    belongs_to :user
    has_many :comments, as: :commentable
    has_many :levels
    serialize :committed, Array
    validates :date_started, presence: true
    before_save :current_level
    acts_as_taggable
    scope :private_submit, -> { where(private_submit: true) }
    scope :public_submit, -> { where(private_submit: false) }

attr_accessor :missed_one, :missed_two, :missed_three

    def save_with_current_level
        self.levels.build
        self.levels.build
        self.levels.build
        self.levels.build
        self.levels.build
        self.save
    end

    def self.committed_for_today
    today_name = Date::DAYNAMES[Date.today.wday].downcase
    ids = all.select { |h| h.committed.include? today_name }.map(&:id)
    where(id: ids)
  end 

    def current_level_strike
      levels[current_level - 1] # remember arrays indexes start at 0
    end

    def current_level
            return 0 unless date_started
          def committed_wdays
            committed.map do |day|    
              Date::DAYNAMES.index(day.titleize)
            end
          end

          def n_days
            ((date_started.to_date)..Date.today).count do |date| 
              committed_wdays.include? date.wday
            end - self.missed_days
          end     

      case n_days     
          when 0..9
            1
          when 10..24
            2
          when 25..44
            3
          when 45..69
            4
          when 70..99
            5
          else
            6
        end
    end
  end

days_missed_controller

class DaysMissedController < ApplicationController
  before_action :logged_in_user, only: [:create, :destroy]

  def create
    habit = Habit.find(params[:habit_id])
    habit.missed_days = habit.missed_days + 1
    habit.save!
    level = habit.levels.find(params[:level_id])
    level.missed_days = level.missed_days + 1
    level.save!
    head :ok # this returns an empty response with a 200 success status code
  end

  def destroy
    habit = Habit.find(params[:habit_id])
    habit.missed_days = habit.missed_days - 1
    habit.save
    level = habit.levels.find(params[:level_id])
    level.missed_days = level.missed_days - 1
    level.save!
    head :ok # this returns an empty response with a 200 success status code
  end
end

这是它的要点https://gist.github.com/RallyWithGalli/c66dee6dfb9ab5d338c2

如果您需要任何进一步的解释、代码或图片,请告诉我:)

【问题讨论】:

    标签: javascript ruby ajax checkbox


    【解决方案1】:

    最简单的方法是使用本地存储(存储在用户浏览器中)。该功能存在于现代浏览器中,因此当您不需要支持旧版浏览器时,它是最佳选择。

    用法也简单的难以置信,只需在“localStorage”变量上设置和读取属性即可:

    # Set one value
    localStorage.myapp_level1_flag1 = true;
    
    # read the value
    if (localStorage.myapp_level1_flag1) {
       ...
    }
    

    你当然应该给变量起有意义的名字。分配给 localStorage 的值将跨会话保存。还有一个变量“sessionStorage”,它只保存一个会话的数据。

    此外,数据由设置的域分隔。所以域 X 不能访问域 Y 的数据集。

    从 IE8 开始大致支持本地存储,并且比 cookie 具有优势,即数据不会在每次请求时都传输到服务器。在本地存储存在之前,使用 cookie 会产生一些性能开销。

    集成

    我建议在您的代码中的两个位置集成本地存储(如果我理解您的 JS 大纲正确的话):

    (当然,你说你对 JS 不太了解,这使得 事情要困难得多,因为解决方案完全取决于 在浏览器端的本地存储上——但否则你需要 从您的服务器端传输所有数据(这可能是必要的 从长远来看,以防止数据重复))

    第一个位置:当你创建复选框时(只是一个粗略的例子):

    if (localStorage.habit_level1_flag1) {
        $(this).parent().append($('<input type="checkbox" class="habit-check" checked>'));
    }
    else {
        $(this).parent().append($('<input type="checkbox" class="habit-check">'));
    }
    

    另一个位置在更改处理程序处:

    if ($(this).is(":checked")) {
      $.ajax({
        url: "/habits/" + habit + "/levels/" + level + "/days_missed",
        method: "POST"
      });
      localStorage.setItem("habit_"+habit+"_"+level, true);
    } else {
      $.ajax({
        url: "/habits/" + habit + "/levels/" + level + "/days_missed/1",
        method: "DELETE"
      });
      localStorage.setItem("habit_"+habit+"_"+level, true);
    }
    

    在此处查看有关localStorage 的更多信息。

    【讨论】:

    • 感谢 Juergen 深思熟虑的解释 :) 我只是不明白如何将它与我提供的代码集成。你说它非常简单,我当然希望你是对的。我把它放在habit.js 的顶部吗?我不熟悉javascript的内部工作原理。这是一种我还没有自学的语言,但我希望在启动我的应用程序之前完成这一功能。
    • 我添加了一些粗略的集成提示。但是您可能还想,是否要将信息存储在服务器上并以类似的方式从那里提取信息(在创建复选框时进行读取 AJAX 调用)。
    • @AnthonyGalli.com:抱歉忘了给你发个电话,我不知道,如果你没有收到国旗。阅读我之前的评论。
    • 再次感谢@Juergen!我听到你的声音响亮而清晰。当我将第一个选项添加到文件中的不同位置时,它并没有什么时髦的东西,可能只是因为它是一个粗略的例子。我更喜欢第二个选项,因为它更像是一种集成,尽管从我所看到的来看这没有影响。我很惊讶这会如此困难,我以为我用谦虚的隆隆声回答克服了困难:/ stackoverflow.com/questions/30109624/…
    • 不要期望 StackOverflow 提供完整的解决方案。这不是它存在的原因。当你不知道如何去适配 JS 部分的时候,你就真的陷入了糟糕的境地。我认为,最好找一个具有 JS 专业知识的人来帮助您处理相关的 AJAX 调用。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-07-07
    • 1970-01-01
    • 2017-02-12
    • 1970-01-01
    • 2014-01-16
    • 1970-01-01
    • 2014-11-29
    相关资源
    最近更新 更多