twitter-bootstrap Bootstrap data-spy="affix" 不适用于 Angular View 更改

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/23638925/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-10-21 20:43:01  来源:igfitidea点击:

Bootstrap data-spy="affix" not working on Angular View change

cssangularjstwitter-bootstrapaffixng-view

提问by PGallagher

I'm trying to figure out why my affix-ed panel isn't staying put when I change my Angular view.

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

I've added the affix property directly to the panel on the first page (details), and left it in the data-spy only in the second page (flights).

我已将词缀属性直接添加到第一页(详细信息)的面板中,并仅将其留在第二页(航班)中的数据间谍中。

In a full blown web version, if I refresh the flights page, suddenly the affix kicks in, and stays put when I scroll, but doesn't if I just navigate to the page using Angular.

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

It looks like the affix isn't being added to the class by Bootstrap when I navigate between views.

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

HTML:

HTML:

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

CSS:

CSS:

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

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

Here's a Plunker..

这是一个Plunker..

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

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

I found a similair question here:

我在这里找到了一个类似的问题:

Twitter Bootstrap: Affix not triggering in single page application

Twitter Bootstrap:在单页应用程序中不触发词缀

But I couldn't figure out how to apply that to my problem here...

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

Any help would be great!

任何帮助都会很棒!

回答by jsparks

Angular UI Utils(notAngular UI Bootstrap, as mentioned in the comments) has a Scrollfix directive that can be used in place of Affix. I had the same problem as you with Affix not working after changing views. I tried adding Angular UI Scrollfix to my app and so far it looks like it will meet my needs.

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

Here is a helpful Stack Overflow post I found with more explanation and examples: Angular ui-utils scrollfix.

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

回答by Gadget Blaster

If you don't want to use UI Bootstrap or UI Utils in favor of the plain old Bootstrap 3 affix, this affix directive wrapper is working good for me on my single page angular app. I'm using the AngularUI Router.

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

Apply the affix the first time the directive is loaded. Then clear it on $stateChagneSuccesswith this: $element.removeData('bs.affix').removeClass('affix affix-top affix-bottom');as seen here: Resetting / changing the offset of bootstrap affix, and then re-apply it. Let me know if anything I'm doing here is painfully ugly, though I like the simplicity and I like leveraging the default Bootstrap JS lib.

第一次加载指令时应用词缀。然后$stateChagneSuccess用这个清除它:$element.removeData('bs.affix').removeClass('affix affix-top affix-bottom');如下所示:重置/更改 bootstrap 词缀的偏移量,然后重新应用它。如果我在这里做的任何事情都非常丑陋,请告诉我,尽管我喜欢简单并且喜欢利用默认的 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();

        }
    };
}]);

回答by kernel

I prefer to hook on the original data-spy="scroll"bootstrap bindings - for better migration from a clickdummy to production - and apply the original bootstrap functionality to it, because Angular-UI is (at least for me) an unacceptable mess.

我更喜欢挂钩原始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
            }
          });
        }
      });
    }
  }
})();

回答by Robert Messerle

This is an old question, but I recently stumbled upon it when rewriting my website as an AngularJS app. I was also using the Bootstrap Affix plugin (including updating active class on scroll), and was unable to find a plugin that worked quite like what I was looking for, so I wrote my own directive.

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

See it in action: http://bobbograph.com/#/api

看到它在行动:http: //bobbograph.com/#/api

Note: The value provided to the directive is the top offset.

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

The JavaScript:

JavaScript:

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

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

The HTML (Jade)

HTML(玉)

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

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

回答by Faisal Feroz

It doesn't work because the specific events are not fired on which affix is bound to. In a Single Page Application as in your case the page is loaded only once so any logic that is bound to page loaded and similar events fail. Things will work fine if you reload the page.

它不起作用,因为特定事件不会被绑定到哪个词缀上。在与您的情况一样的单页应用程序中,页面仅加载一次,因此绑定到页面加载和类似事件的任何逻辑都会失败。如果您重新加载页面,一切都会正常进行。

The solution is to use angularized way. One of the comments suggest using angular-strap a try as it has an affix directive for the exact same purpose.

解决方案是使用角度化的方式。其中一条评论建议尝试使用 angular-strap,因为它具有用于完全相同目的的词缀指令。

I came across a similar situation and ended up using MacGyverIt works really well and is simple to use.

我遇到了类似的情况,最终使用了MacGyver它工作得很好,使用起来也很简单。