【问题标题】:How to set widget data from local storage using gridstack.js如何使用 gridstack.js 从本地存储设置小部件数据
【发布时间】:2018-11-27 12:55:14
【问题描述】:

场景

我有一个仪表板,其中一些小部件分组到用户可以单击的选项卡中。小部件具有默认的起始位置,包括高度和宽度,但如果用户移动或调整它们的大小(使用gridstack.js),我会将新的小部件数据保存到本地存储。

如果用户在选项卡之间单击,新的小部件位置将保持不变。

问题

当用户刷新页面时,会加载默认的小部件位置,而不是本地存储中的数据。我尝试使用getWidgetData() 设置新位置,但没有成功。

我已经检查了我的 grid-layout 数据的本地存储,并且存在新位置。

代码示例

这里是 Codepen,因为我认为 SO 需要 allow-same-origin,因此打破了 sn-p。

// Initialize zurb foundation
$(document).foundation();

$(function() {
  var grid = $('.grid-stack').data('gridstack');

  var options = {
    cellHeight: 40,
    verticalMargin: 28,
    animate: false,
  };

  // Initialize grid-stack widgets
  widgetsInit = function(options) {
    $('.grid-stack').gridstack(options);
    getWidgetData(); // Find and set positions from local storage
  }

  updateVisibleWidgetHeights = function(options) {
    var targetPanel = '.tabs-panel.is-active';

    $(targetPanel + ' .grid-stack .grid-stack-item').each(function(i){
      $(targetPanel + ' .grid-stack').data('gridstack').resize(
        $(targetPanel + ' .grid-stack .grid-stack-item')[i],
        $($(targetPanel + ' .grid-stack .grid-stack-item')[i]).attr('data-gs-width'),
        Math.ceil(($(targetPanel + ' .grid-stack .grid-stack-item .grid-stack-item-content')[i].scrollHeight + $(targetPanel + ' .grid-stack').data('gridstack').opts.verticalMargin) / ($(targetPanel + ' .grid-stack').data('gridstack').cellHeight() + $(targetPanel + ' .grid-stack').data('gridstack').opts.verticalMargin))
      );
    });
  }

  updateAllWidgetHeights = function(options) {
    $('.grid-stack .grid-stack-item').each(function(i){
      $('.grid-stack').data('gridstack').resize(
        $('.grid-stack .grid-stack-item')[i],
        $($('.grid-stack .grid-stack-item')[i]).attr('data-gs-width'),
        Math.ceil(($('.grid-stack .grid-stack-item .grid-stack-item-content')[i].scrollHeight + $('.grid-stack').data('gridstack').opts.verticalMargin) / ($('.grid-stack').data('gridstack').cellHeight() + $('.grid-stack').data('gridstack').opts.verticalMargin))
      );
    });
  }

  getWidgetData = function() {
    // // Load from local storage
    var serialization = null;
    if (serialization = localStorage.getItem("grid-layout")) {
      _.each(JSON.parse(serialization), function (node) {
        // Update each widget's properties from values in storage
        $('.grid-stack-item[data-custom-id='+ node.id +']').attr({
          'data-gs-x': node.x,
          'data-gs-y': node.y,
          'data-gs-width': node.width,
          'data-gs-height': node.height,
        });
      });
    } else {
      console.log("There was no local storage data to read")
    }
  }

  widgetsInit(options);
  updateVisibleWidgetHeights();

  $('.grid-stack').on('change', function (event, items) {
    // Save data to local storage
    var res = _.map($('.grid-stack .grid-stack-item'), function (el) {
      el = $(el);
      node = el.data('_gridstack_node');
      return {
        // Grab widget properties
        id: el.attr('data-custom-id'),
        x: node.x,
        y: node.y,
        width: node.width,
        height: node.height
      };
    });
    localStorage.setItem("grid-layout", JSON.stringify(res))
  });

  // On tab change update widget heights to the height of the content they contain
  $(document).on('change.zf.tabs', function() {
    updateVisibleWidgetHeights();
  })
});
.grid-stack > .grid-stack-item > .grid-stack-item-content {
    background-color: #fff;
    cursor: move;
    border: 1px solid #e3e3e3;
    border-radius: 4px;
	padding: 1rem;
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/0.4.0/gridstack.min.css" rel="stylesheet"/>
<link href="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.4.3/css/foundation.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/0.4.0/gridstack.min.js'></script>
<script src='https://cdnjs.cloudflare.com/ajax/libs/gridstack.js/0.4.0/gridstack.jQueryUI.min.js'></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.4.3/js/foundation.min.js"></script>


<ul class="tabs" data-tabs id="example-tabs" data-deep-link="true" data-update-history="true" data-match-height="false">
  <li class="tabs-title is-active"><a href="#panel1" aria-selected="true">Tab 1</a></li>
  <li class="tabs-title"><a href="#panel2">Tab 2</a></li>
</ul>

<div class="tabs-content unstyled" data-tabs-content="example-tabs">
  <div class="tabs-panel is-active" id="panel1">
    <div class="grid-stack">
      <div class="grid-stack-item" data-gs-x="0" data-gs-y="0" data-gs-width="4" data-gs-height="2">
        <div class="grid-stack-item-content">#1</div>
      </div>
      <div class="grid-stack-item" data-gs-x="4" data-gs-y="0" data-gs-width="4" data-gs-height="2">
        <div class="grid-stack-item-content">#2</div>
      </div>
      <div class="grid-stack-item" data-gs-x="8" data-gs-y="0"data-gs-width="4" data-gs-height="2">
        <div class="grid-stack-item-content">#3</div>
      </div>
    </div>
  </div>
  <div class="tabs-panel" id="panel2">
    <div class="grid-stack">
      <div class="grid-stack-item" data-gs-x="0" data-gs-y="0" data-gs-width="4" data-gs-height="2">
        <div class="grid-stack-item-content">#4</div>
      </div>
      <div class="grid-stack-item" data-gs-x="4" data-gs-y="0" data-gs-width="4" data-gs-height="2">
        <div class="grid-stack-item-content">#5</div>
      </div>
      <div class="grid-stack-item" data-gs-x="8" data-gs-y="0" data-gs-width="4" data-gs-height="2">
        <div class="grid-stack-item-content">#6</div>
      </div>
    </div>
  </div>
</div>

【问题讨论】:

    标签: jquery html css zurb-foundation gridstack


    【解决方案1】:

    你需要调查一些事情。

    可用的默认示例适用于单个实例,而您有多个。

    您正在一次性保存和加载gridstack,这意味着您无法跟踪元素grid-stack-item,并且您也无法跟踪哪个点属于第一个选项卡或第二个选项卡的哪个实例,

    因此,即使您让它工作,它也会尝试将所有 6 个不同的小部件放置在第一个选项卡中,而不是将其加载到各自的选项卡中。

    所以需要对以下内容进行修改

    • $('.grid-stack').on('change', function (event, items) {

    • getWidgetData()

    • 在 grid-stack-items 中分配 id 或 custom-data-id 属性,以便它们具有唯一标识符

    • 将选项卡包裹在 ID 为 tabs-cotnainer 的容器内。

    关于 gridstack 的事件更改,您应该创建一个 json 对象,该对象包含专用于选项卡的部分中的点,如下所示。

    {
      "items": {
        "panel1": [
          {
            "id": "panel1-item1",
            "x": 0,
            "y": 0,
            "width": 4,
            "height": 2
          },
          {
            "id": "panel1-item2",
            "x": 4,
            "y": 0,
            "width": 4,
            "height": 2
          },
          {
            "id": "panel1-item3",
            "x": 8,
            "y": 0,
            "width": 4,
            "height": 2
          }
        ],
        "panel2": [
          {
            "id": "panel2-item1",
            "x": 0,
            "y": 0,
            "width": 4,
            "height": 2
          },
          {
            "id": "panel2-item2",
            "x": 4,
            "y": 0,
            "width": 4,
            "height": 2
          },
          {
            "id": "panel2-item3",
            "x": 8,
            "y": 0,
            "width": 4,
            "height": 2
          }
        ]
      }
    }
    

    替换为以下内容

    $('.grid-stack').on('change', function (event, items) {
        let tabs = $('#tabs-container >ul >li');
        let totalTabs = $('#tabs-container >ul >li').length;
    
        let storagePositions = {
            items: {}
        };
        $.each(tabs, function (index, elem) {
            let panel = $(elem).find('a').attr('href').replace("#", '');
            let stackItems = $('#' + panel + ' .grid-stack .grid-stack-item');
    
            storagePositions.items[panel] = _.map(stackItems, function (el) {
    
                el = $(el);
                node = el.data('_gridstack_node');
                //console.log(node);
    
                return { // Grab widget properties
                    id: el.attr('data-custom-id'),
                    x: node.x,
                    y: node.y,
                    width: node.width,
                    height: node.height
                };
            });
        });
    
        // Save data to local storage
        localStorage.setItem("grid-layout", JSON.stringify(storagePositions))
    });
    

    然后以类似的方式加载选项卡

    getWidgetData = function () {
    
        // // Load from local storage
        var serialization = null;
        let tabs = $('#tabs-container >ul >li');
        let totalTabs = $('#tabs-container >ul >li').length;
    
        if (localStorage.getItem("grid-layout") !== null) {
    
            serialization = JSON.parse(localStorage.getItem("grid-layout"));
    
    
    
            $.each(tabs, function (index, elem) {
                let panel = $(elem).find('a').attr('href').replace('#', '');
                let myGrid = $('#' + panel + ' .grid-stack').data('gridstack')
    
                var items = GridStackUI.Utils.sort(serialization.items[panel]);
                _.each(items, function (node) {
    
                    myGrid.update($('div[data-custom-id="' + node.id + '"]'),
                        node.x, node.y, node.width, node.height);
                });
            });
        } else {
            console.log("There was no local storage data to read")
        }
    }
    

    您更新后的 HTML 将如下所示

    <div id="tabs-container">
        <ul class="tabs dashboard-tabs" data-tabs id="example-tabs" data-deep-link="true" data-update-history="true" data-match-height="false">
            <li class="tabs-title is-active">
                <a href="#panel1" aria-selected="true">Tab 1</a>
            </li>
            <li class="tabs-title">
                <a href="#panel2">Tab 2</a>
            </li>
        </ul>
    
        <div class="tabs-content unstyled" data-tabs-content="example-tabs">
            <div class="tabs-panel is-active" id="panel1">
                <div class="grid-stack">
                    <div class="grid-stack-item" data-custom-id="panel1-item1" data-gs-x="0" data-gs-y="0" data-gs-width="4" data-gs-height="2">
                        <div class="grid-stack-item-content">#1</div>
                    </div>
                    <div class="grid-stack-item" data-custom-id="panel1-item2" data-gs-x="4" data-gs-y="0" data-gs-width="4" data-gs-height="2">
                        <div class="grid-stack-item-content">#2</div>
                    </div>
                    <div class="grid-stack-item" data-custom-id="panel1-item3" data-gs-x="8" data-gs-y="0" data-gs-width="4" data-gs-height="2">
                        <div class="grid-stack-item-content">#3</div>
                    </div>
                </div>
            </div>
            <div class="tabs-panel" id="panel2">
                <div class="grid-stack">
                    <div class="grid-stack-item" data-custom-id="panel2-item1" data-gs-x="0" data-gs-y="0" data-gs-width="4" data-gs-height="2">
                        <div class="grid-stack-item-content">#4</div>
                    </div>
                    <div class="grid-stack-item" data-custom-id="panel2-item2" data-gs-x="4" data-gs-y="0" data-gs-width="4" data-gs-height="2">
                        <div class="grid-stack-item-content">#5</div>
                    </div>
                    <div class="grid-stack-item" data-custom-id="panel2-item3" data-gs-x="8" data-gs-y="0" data-gs-width="4" data-gs-height="2">
                        <div class="grid-stack-item-content">#6</div>
                    </div>
                </div>
            </div>
        </div>
    </div>
    

    在JSFIDDLE 上查看完整的工作演示,您可以更新两个选项卡中的位置,然后尝试刷新页面,它将显示更新的位置。

    注意:只需在脚本顶部写localStorage.removeItem("grid-layout") 删除之前的值一次,它们会在第一次运行后删除此行。

    【讨论】:

      猜你喜欢
      • 2020-03-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-01
      • 2018-04-09
      • 1970-01-01
      • 2015-02-16
      • 2020-08-10
      相关资源
      最近更新 更多