Bootstrap data-spy="affix" 不适用于 Angular 视图更改

Posted

技术标签:

【中文标题】Bootstrap data-spy="affix" 不适用于 Angular 视图更改【英文标题】:Bootstrap data-spy="affix" not working on Angular View change 【发布时间】:2014-07-01 13:55:25 【问题描述】:

我试图弄清楚为什么当我更改 Angular 视图时我的affix-ed 面板没有保持原样。

我已将 affix 属性直接添加到第一页(详细信息)的面板中,并将其仅留在第二页(航班)的 data-spy 中。

在完整的网络版本中,如果我刷新航班页面,词缀会突然启动,并在我滚动时保持不变,但如果我只是使用 Angular 导航到该页面,则不会。

当我在视图之间导航时,Bootstrap 似乎没有将词缀添加到类中。

HTML:

<div class="panel panel-primary mySidebar" id="sidebar" 
    data-spy="affix" data-offset-top="0" data-offset-bottom="200">

CSS:

.mySidebar.affix 
    position: fixed;
    top: 250px;  


.mySidebar.affix-bottom 
    position: absolute;
    top: auto;
    bottom: 450px;  

这是一个Plunker..

http://plnkr.co/edit/S0Bc50?p=preview

我在这里发现了一个类似的问题:

Twitter Bootstrap: Affix not triggering in single page application

但我不知道如何将其应用于我的问题......

任何帮助都会很棒!

【问题讨论】:

您考虑过使用github.com/angular-ui/bootstrap 吗? 我实际上没有... 这有什么帮助?干杯! @cvrebert Angular UI Bootstrap 似乎没有 Affix 指令 但是 Angular UI Utils 有一个 Scrollfix 指令 你也可以只从组件触发它。它工作我试过getbootstrap.com/docs/3.4/javascript/#via-javascript-5 【参考方案1】:

Angular UI Utils(not Angular UI Bootstrap,如 cmets 中所述)有一个 Scrollfix 指令,可以用来代替 Affix。我遇到了和你一样的问题,改变视图后 Affix 不起作用。我尝试将 Angular UI Scrollfix 添加到我的应用程序中,到目前为止它看起来可以满足我的需求。

这是我发现的一篇有用的 Stack Overflow 帖子,其中包含更多解释和示例:Angular ui-utils scrollfix。

【讨论】:

谢谢...我会试一试的!【参考方案2】:

如果您不想使用 UI Bootstrap 或 UI Utils 来支持普通的旧 Bootstrap 3 词缀,那么这个词缀指令包装器在我的单页 Angular 应用程序上对我很有用。我正在使用 AngularUI 路由器。

第一次加载指令时应用词缀。然后在$stateChagneSuccess 上清除它:$element.removeData('bs.affix').removeClass('affix affix-top affix-bottom'); 如此处所示:Resetting / changing the offset of bootstrap affix,然后重新应用它。如果我在这里做的任何事情都很难看,请告诉我,尽管我喜欢简单并且喜欢利用默认的 Bootstrap JS 库。

myApp.directive('affix', ['$rootScope', '$timeout', function($rootScope, $timeout) 
    return 
        link: function($scope, $element, $attrs) 

            function applyAffix() 
                $timeout(function()                    
                    $element.affix( offset:  top: $attrs.affix  );
                );
            

            $rootScope.$on('$stateChangeSuccess', function() 
                $element.removeData('bs.affix').removeClass('affix affix-top affix-bottom');
                applyAffix();
            );

            applyAffix();

        
    ;
]);

【讨论】:

【参考方案3】:

我更喜欢挂钩原始的 data-spy="scroll" 引导绑定 - 以便更好地从 clickdummy 迁移到生产环境 - 并将原始引导功能应用于它,因为 Angular-UI(至少对我而言)是不可接受的混乱。

(function () 
  'use strict';

  angular
    .module('app.core')
    .directive('spy', spy);


  function spy() 
    return 
      restrict: 'A',
      link: link
    ;

    function link(scope, element, attrs) 

      // Dom ready
      $(function () 
        if (attrs.spy === 'affix') 
          $(element).affix(
            offset: 
              top: attrs.offsetTop || 10
              // bottom: attrs.offsetBottom || 10
            
          );
        
      );
    
  
)();

【讨论】:

【参考方案4】:

这是一个老问题,但我最近在将我的网站重写为 AngularJS 应用程序时偶然发现了这个问题。我也在使用 Bootstrap Affix 插件(包括在滚动时更新活动类),但无法找到与我正在寻找的功能非常相似的插件,所以我编写了自己的指令。

查看实际操作:http://bobbograph.com/#/api

注意:提供给指令的值是顶部偏移量。

JavaScript:

https://github.com/robertmesserle/Bobbograph/blob/v3/www/js/site.js#L102

app.directive('rmAffix', function ($window) 
  var body = document.body,
      win = document.defaultView,
      docElem = document.documentElement,
      isBoxModel = (function () 
        var box = document.createElement('div'),
            isBoxModel;
        box.style.paddingLeft = box.style.width = "1px";
        body.appendChild(box);
        isBoxModel = box.offsetWidth == 2;
        body.removeChild(box);
        return isBoxModel;
      )();
  function getTop (element) 
    var box = element.getBoundingClientRect(),
        clientTop  = docElem.clientTop  || body.clientTop  || 0,
        scrollTop  = win.pageYOffset || isBoxModel && docElem.scrollTop || body.scrollTop;
    return box.top + scrollTop - clientTop;
  
  return function ($scope, $element, $attrs) 
    var offset = $scope.$eval($attrs.rmAffix),
        elemTop = getTop($element[0]),
        $links = $element.find('li'),
        linkTops = [];
    angular.forEach($links, function ($link) 
      var $a = angular.element($link).find('a'),
          href = $a.attr('href').substr(1),
          target = document.getElementById(href),
          elemTop = getTop(target);
      linkTops.push(elemTop);
      $a.on('click', function (event) 
        window.scrollTo(0, elemTop - offset);
        event.preventDefault();
      );
    );
    angular.element($window).on('scroll', function (event) 
      var top = window.pageYOffset,
          index;
      if (top > elemTop - offset) $element.addClass('affix');
      else $element.removeClass('affix');
      //-- remove selected class from all links
      $links.removeClass('active');
      //-- find the closest element
      for (index = 1; index < linkTops.length; index++) 
        if (linkTops[index] - 100 > top) break;
      
      angular.element($links[index - 1]).addClass('active');
    );
  ;
);

html(翡翠)

https://github.com/robertmesserle/Bobbograph/blob/v3/www/api.jade#L288

ul.nav.nav-stacked.nav-pills(rm-affix=70)
  li.active: a( href="#basic" ) Basic Usage
  li: a( href="#options"   ) Options
  li: a( href="#data"      ) Data
  li: a( href="#padding"   ) Padding

【讨论】:

【参考方案5】:

它不起作用,因为特定事件不会在词缀绑定到时触发。在您的情况下的单页应用程序中,页面仅加载一次,因此绑定到页面加载和类似事件的任何逻辑都会失败。如果您重新加载页面,一切都会好起来的。

解决方法是使用棱角分明的方式。其中一个 cmets 建议尝试使用 angular-strap,因为它具有用于完全相同目的的 affix 指令。

我遇到了类似的情况,最终使用了MacGyver,效果非常好,而且使用简单。

【讨论】:

谢谢...我会试一试的!

以上是关于Bootstrap data-spy="affix" 不适用于 Angular 视图更改的主要内容,如果未能解决你的问题,请参考以下文章

附加导航

20161019复习笔记

bootstrap模态框怎么传递参数?

六、bootstrap按钮、输入框

怎么取消bootstrap默认表格的分页

bootstrap-select插件 没有效果