2014-05-13 16 views
16

Ich versuche herauszufinden, warum mein affix -ed Panel nicht bleibt, wenn ich meine Angular-Ansicht ändere.bootstrap data-spy = "affix" funktioniert nicht bei "Angular View" ändern

Ich habe die Affix-Eigenschaft direkt zum Panel auf der ersten Seite hinzugefügt (Details), und es im Datenspion nur auf der zweiten Seite (Flights) gelassen.

In einer vollständigen Web-Version, wenn ich die Flights-Seite aktualisieren, plötzlich die Affix setzt und bleibt beim Scrollen, aber nicht wenn ich nur auf die Seite mit Angular navigieren.

Es sieht so aus, als würde der Affix der Klasse nicht durch Bootstrap hinzugefügt werden, wenn ich zwischen Ansichten navigiere.

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

Hier ist ein Plunker ..

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

ich ein similair ques gefunden Tion hier:

Twitter Bootstrap: Affix not triggering in single page application

Aber ich kann nicht herausfinden, wie das hier mein Problem anzuwenden ...

Jede Hilfe wäre toll!

+0

Haben Sie über die Verwendung von https://github.com/angular-ui/bootstrap nachgedacht? – cvrebert

+0

Ich habe eigentlich nicht ... Was bietet dieses Angebot an? Prost! – PGallagher

+0

@cvrebert Angular UI Bootstrap scheint keine Affix-Direktive zu haben – jsparks

Antwort

2

Es funktioniert nicht, da die spezifischen Ereignisse nicht ausgelöst werden, an die Affix gebunden ist. In einer Einzelseitenanwendung wie in Ihrem Fall wird die Seite nur einmal geladen, so dass jede Logik, die an die Seite gebunden ist, und ähnliche Ereignisse fehlschlagen. Die Dinge funktionieren gut, wenn Sie die Seite neu laden.

Die Lösung ist, winkelförmig zu verwenden. Einer der Kommentare schlägt vor, eckigen Gurt einen Versuch zu verwenden, da es eine Affix-Anweisung für genau den gleichen Zweck hat.

Ich stieß auf eine ähnliche Situation und endete mit MacGyver Es funktioniert wirklich gut und ist einfach zu bedienen.

+0

Danke ... Ich werde es versuchen! – PGallagher

13

Angular UI Utils (nicht Angular UI Bootstrap, wie sie in den Kommentaren erwähnt) eine Scrollfix-Direktive, die anstelle von Affix verwendet werden kann. Ich hatte das selbe Problem wie Du mit Affix nach dem Ändern der Ansichten nicht funktionierst. Ich habe versucht, Angular UI Scrollfix zu meiner App hinzuzufügen und bis jetzt sieht es so aus, als würde es meine Bedürfnisse erfüllen.

Hier ist eine hilfreiche Stack Overflow Post, die ich mit mehr Erklärungen und Beispielen gefunden habe: Angular ui-utils scrollfix.

+0

Danke ... Ich werde es versuchen! – PGallagher

3

Das ist eine alte Frage, aber ich bin kürzlich darüber gestolpert, als ich meine Website als AngularJS-App umgeschrieben habe. Ich habe auch das Bootstrap Affix-Plugin verwendet (einschließlich der Aktualisierung der aktiven Klasse bei scroll), und konnte kein Plugin finden, das genau so funktionierte, wie ich es wollte, also schrieb ich meine eigene Direktive.

Sehen sie in Aktion: http://bobbograph.com/#/api

Hinweis: Die an der Richtlinie vorgesehenen Wert versetzt die Spitze ist.

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

Die HTML (Jade)

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 
7

Wenn Sie keine UI Bootstrap oder UI Utils verwenden möchten in Gunst der einfachen alten Bootstrap 3 Affix, dieser Affix Direktive Wrapper funktioniert gut für mich auf meiner einseitigen eckigen App. Ich benutze den AngularUI Router.

Wenden Sie den Affix an, wenn die Direktive zum ersten Mal geladen wird. Dann löschen Sie es auf $stateChagneSuccess mit diesem: $element.removeData('bs.affix').removeClass('affix affix-top affix-bottom'); wie hier zu sehen: Resetting/changing the offset of bootstrap affix, und dann erneut anwenden. Lassen Sie mich wissen, dass alles, was ich hier mache, schmerzhaft hässlich ist, obwohl ich die Einfachheit mag und die Standard-Bootstrap JS-Lib verwenden möchte.

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(); 

     } 
    }; 
}]); 
+0

Es hat funktioniert !! Vielen Dank –

4

Ich ziehe es auf den ursprünglichen data-spy="scroll" Bootstrap-Bindungen Haken - für eine bessere Migration von einem clickdummy zur Produktion - und die Original-Bootstrap-Funktionalität für sie gelten, da Angular-UI (zumindest für mich) ist ein nicht hinnehmbares Chaos .

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