Bootstrap 4:如何初始化模式包装器插件

时间:2019-02-10 09:32:34

标签: twitter-bootstrap bootstrap-4 bootstrap-modal

我已经构建了一个模式包装器插件(Bootstrap 4),该插件可以根据需要动态创建对话框。使用每个触发器按钮的唯一选择器初始化插件时,我可以创建该插件的多个实例。

我想初始化一次,但是每个启动按钮都有单独的实例。问题在于该插件将忽略通过数据属性为除第一个按钮以外的所有按钮设置的选项。无论单击哪个按钮,都会生成完全相同的模式,并且该模式基于队列中第一个按钮上传递的选项。

这是我当前设置的摘要。谁能看到我可能缺少的东西?

这是一个示例设置:

初始化

$('.open-modal').myModal();

两个用于打开模式的示例按钮

// Button 1
<button type="button" class="btn open-modal" data-title="Modal 1" data-target="myModal1" data-remote="test.html">Open modal 1</button>

// Button 2 data attributes are ignored. The Modal always renders with options from button 1
<button type="button" class="btn open-modal" data-title="Modal 2" data-position="right" data-target="myModal2" data-remote="test2.html">Open modal 2</button>

插件

... 

const defaults = {      
      type: 'basic',       
      id: 'myModal' + helper.getRandomInt(9999, 1000),      
      title: window.document.title,    
      position: '', //
      remote: null, // content to be loaded via Ajax
      target: 'myModal', // id of the generated modal
      ...  
};

class Modal {
  constructor(el, options) {            
    this._$el = $(el);
    this._el = el;
    this._options = options;
    this._$el.data(PLUGIN_NAME, this);
    this._metadata = this._$el.data();
    this._defaults = this.getDefaults();           
    this._opts = $.extend(true, {}, this._defaults, this._options, this._metadata);            

  }

  // render modal
  render(event) {    
    let cls = this;              
    let $el = this._$el;
    let _bodyID = cls._opts.bodyID;
    let _type = cls._opts.type;    
    let $tpl = $(cls.buildTemplate());        

    $tpl.appendTo("body").modal({
      show: true,
      backdrop: cls._opts.backdrop,
      keyboard: false
    });

    // show content
    if (_type == 'delete') {        
        var $mdlBodyID = $(_bodyID);
        var $warningContainer = $('<p>');
        $warningContainer.text(cls._opts.content).appendTo($mdlBodyID);        
    } else {
        let basicType = _type || 'basic';
        cls.log(`${basicType} modal launched`);
        $.ajax({
          url: cls._opts.remote,
        }).done(cls.onSuccess).fail(cls.onError);
    }                
    // remove modal from DOM when closed
    $tpl.on(cls._opts.hideEvent, {this: cls}, cls.onHidden);
    ...
  }

  ...

}

// pluign definition

$.fn[PLUGIN_NAME] = function (options) {

  var items = this;
  if (items.length) {
      var bm = new Modal(items, options);      
      return items.each(function(e) {   
        let $item = $(this);    
        $item.on('click', function(event) {                
          event.stopPropagation();
          event.preventDefault();
          bm.render(event.type);
        })        
      });
  }
}

编辑2:对代码段进行快速重新排序以更加清晰

1 个答案:

答案 0 :(得分:0)

归结为在$.extend循环内将each方法移至插件定义。

  if (items.length) {
      var bm = new Modal(items, options);      
      return items.each(function(e) {   
        let $item = $(this);    
        // override defaults with options or data attributes
        let settings = $.extend(true, {}, defaults, options, $item.data());            
        $item.on('click', function(event) {                
          event.stopPropagation();
          event.preventDefault();
          bm.render(event.type, settings);
        })        
      });
  }

然后,只需将这些设置传递回render方法即可,该方法现在仅接受第二个参数。

如果任何人都可以使用,则对render方法进行以下编辑:

 // render modal
  render(event, settings) {    
    let cls = this;              
    let $el = this._$el;
    let _bodyID = cls._opts.bodyID;
    let _type = cls._opts.type;    
    let $tpl = $(cls.buildTemplate(settings));        

    $tpl.appendTo("body").modal({
      show: true,
      backdrop: settings.backdrop,
      keyboard: false
    });

    // show content
    if (_type == 'delete') {        
        var $mdlBodyID = $(_bodyID);
        var $warningContainer = $('<p>');
        $warningContainer.text(settings.content).appendTo($mdlBodyID);        
    } else {
        let basicType = _type || 'basic';
        cls.log(`${basicType} modal launched`);
        $.ajax({
          url: settings.remote,
        }).done(cls.onSuccess).fail(cls.onError);
    }                
    // remove modal from DOM when closed
    $tpl.on(settings.hideEvent, {this: cls}, cls.onHidden);
    ...
  }