使路线与 Bootstrap 轮播中的幻灯片相对应,并在幻灯片更改时更新该路线

Make route to correspond to slide within Bootstrap carousel and update that route when slide changes

我正在使用 ui-bootstrap 和 ui-路由器。我想要一个 URL 结构,允许我 link 到轮播中的幻灯片,例如

/carousel/123/slide/789

这将加载轮播“123”并将幻灯片“789”显示为活动幻灯片。

我还希望更新此 URL 以反映正在显示的任何幻灯片。

我已经尝试了几种更新路线的方法,虽然它按预期工作,但它没有完成工作,因为在某些情况下它在逻辑上不起作用。

我知道让控制器知道 DOM 并像下面的示例代码那样使用 JQuery 不是 Angular 方式,但我不认为这对我要解决的问题很重要。 有人要求我向此应用程序添加路由,而不是实施最佳实践。如果将内容移动到指令或以其他方式修复它会帮助我解决当前的问题,无论如何,我愿意,否则它必须留到另一天。

我尝试的第一件事没有激活加载的第一个页面的路由:

在我的控制器中,

jQuery($scope.data.carouselSelector).on('slide.bs.carousel', function () {
  var newRoute = $state.href($state.current, {photoId:currentPhoto.id});
  $location.path(newRoute);
}

在我的配置中,

.run(['$urlRouter', function ($urlRouter) {
    $rootScope.$on('$locationChangeSuccess', function(e, newUrl, oldUrl) {

      e.preventDefault();

      // This doesn't work because newUrl and oldUrl are the same when the app fires up at a route
      if (newUrl !== oldUrl) {
        $urlRouter.sync();
      } else {
        console.log('SKIP SYNCING');
      }

    });
    $urlRouter.listen();
  }]);

我尝试的第二件事是添加一个查询参数,指示应该跳过同步路由,因为更改已经发生。

在我的控制器中,

jQuery($scope.data.carouselSelector).on('slide.bs.carousel', function () {
  var newRoute = $state.href($state.current, {photoId:currentPhoto.id});
  $location.path(newRoute + '?ok=1');
}

在我的配置中,

.run(['$urlRouter', function ($urlRouter) {
    $rootScope.$on('$locationChangeSuccess', function(e, newUrl, oldUrl) {

      e.preventDefault();

      // I also tried adding a query parameter when the slide changes after the carousel has been loaded. But there is no way of knowing why skipSync=1 is in the URL. A user could have bookmarked it or even just reloaded the poage for instances.
      if (newUrl.indexOf('skipSync=1') !== -1) {
        $urlRouter.sync();
      } else {
        console.log('SKIP SYNCING');
      }
    });
    $urlRouter.listen();
  }]);

为了让事情更复杂一点,轮播处于我这样打开的模态中 -

在我的配置中,

.state("search.photo-view", {
  url: "/photo/:photoId",
  onEnter: ['$state', '$modal', function($state, $modal) {
      $modal.open({
        templateUrl: "photo-fullscreen.html",
        controller: "PhotoFullscreenController"
      }).result.finally(function() {
        $state.go('^');
      });
    }]
  })

在我看来,如果有一种方法可以从配置中知道模式是否已经打开,我可以假设它包含一个旋转木马并且已经在显示我想要的幻灯片。

我最终在配置中跟踪与路线关联的模式是否已经打开,如果模式存在则忽略路线更改。请注意,当模式关闭触发承诺的 'finally':

时,我将变量设置为 null
var myApp = angular.module("myApp", ["ui.router"]);
myApp.config(["$stateProvider", function($stateProvider) {

  var carouselModalInstance, personModalInstance;

  $stateProvider.state("home.photo-view", {
    url: "/photo/:photoId",
    onEnter: ['$rootScope', '$stateParams', '$state', '$modal', '$resource', function($rootScope, $stateParams, $state, $modal, $resource) {

      if (!carouselModalInstance) {
        carouselModalInstance = $modal.open({
          templateUrl: "photo-fullscreen.html",
          controller: "PhotoFullscreenController"
        }).result.finally(function() {
          carouselModalInstance = null;
          $state.go('^');
        });
      }
      }]
    })
}]);

在其他地方(在我的控制器中),我根据事件更新路线 ui bootstrap 当轮播中的幻灯片完成时发出:

jQuery($scope.data.carouselSelector).on('slid.bs.carousel', function () {

    var currentPhoto = getSlideForIndex(getCurrentSlideIndex());

    if (currentPhoto) {
      onPhotoChanged(currentPhoto);

    }

    var newRoute = unescape($state.href($state.current, {photoId:currentPhoto.id}));
    $location.path(newRoute);

});