2014-06-11 337 views
14

嘿,我遇到了我认为是常见的路由问题,但我无法找出解决方案。基本上我的页面有两种状态,基本和高级,我希望两种状态的URL模式相同,但是只加载当前状态的模板(从控制器内部过渡到此模板)AngularUI路由器:具有相同url模式的多个状态

config(function ($stateProvider) { 

    $stateProvider.state('basic', { 
    url: '/:post', 
    templateUrl: function (stateParams) { 
     return 'post-' + stateParams.post + '-tmpl.html'; 
    } 
    }); 

    $stateProvider.state('advanced', { 
    url: '/:post', 
    templateUrl: function (stateParams) { 
     return 'post-' + stateParams.post + '-advanced-tmpl.html'; 
    } 
    }); 
}) 

controller('myCtrl', function ($state) { 
    // 
    // In this case, I would expect only the template from 
    // the advanced state to load, but both templates are trying 
    // to load. 
    $state.transitionTo('advanced', {post: 2}); 
} 

我假设导航到匹配的模式加载给定的状态,这就是为什么当它匹配时,两个模板试图加载。有什么方法可以完成相同的网址模式,但只有基于当前状态的不同模板?

+0

我遇到同样的问题。我认为UI路由器基于状态,而不是URL,但是这证明了相反的 –

+0

你找到了解决方案吗? –

+0

我注意到,在第二次使用ui-sref实现的此配置(您的高级)中单击第二个状态时,会加载正确的模板。 (浏览器地址栏更新,因为它应该是第一次) –

回答

17

假设你不能有两个国家使用相同的URL,你为什么不走和两个状态合并成一个? Ui路由器已经允许你有一个自定义函数来返回模板。你只需要添加一个隐藏的自定义参数(让我们将他advanced调用)的状态声明:

$stateProvider.state('basicOrAdvanced', { 
    url: '/:post', 
    templateUrl: function (stateParams) { 
    if (stateParams.advanced) { 
     return 'post-' + stateParams.post + '-advanced-tmpl.html'; 
    } else { 
     return 'post-' + stateParams.post + '-tmpl.html'; 
    } 
    }, 
    params: { 
    advanced: False 
    } 
}); 

然后你把它叫做:

$state.transitionTo('basicOrAdvanced', {post: 2, advanced: True}) 

对于另一种可能的解决方案嵌套状态和通用控制器,请参阅ui-router的github页面上的问题#217#1096

的解决方案提出有创建第三状态,其控制器做调度工作,而要在(basicadvanced)降落在两个州都有空网址:如果

$stateProvider.state('basicOrAdvanced', { 
    url: '/:post', 
    controller: function($state, $stateParams) { 
    if($stateParams.advanced) { 
     $state.go('advanced', {post: $stateParams.post}); 
    } else { 
     $state.go('basic', {post: $stateParams.post}); 
    } 
    }, 
    params: { 
    advanced: False 
    } 
} 

该解决方案是更好的状态在多个方面不同比简单templateUrl(例如,如果它们具有完全独立的控制器等)


另见another question on StackOverflow about a similar issue

+0

这也适用于ui-sref吗?我明白你的意思,提供解决方案,但我想避免你的方法。如果它不仅与其关联的模板可能发生变化,还会与ui-router状态相关的数据或其他属性呢? –

+0

例如,我有一个用例,其中“:post”是多语言上下文中的动态值。所以我想要一个名字为'about'和url':page'的国家能够拥有一个url/about-english和/ about-dutch。还有其他类似的状态有不同的数据属性(和其他)绑定到这些特定的状态 –

+0

它应该与ui-sref一起工作,是的。 – DzinX

-1

您需要使用嵌套的状态

config(function ($stateProvider) { 


    $stateProvider.state('post', { 
    url: '/:post', 
    templateUrl: function (stateParams) { 
     return 'post-' + stateParams.post + '-advanced-tmpl.html'; 
    } 
    }); 

    $stateProvider.state('post.basic', { 
    url: '/:post', 
    templateUrl: function (stateParams) { 
     return 'post-' + stateParams.post + '-tmpl.html'; 
    } 
    }); 

}) 

controller('myCtrl', function ($state, $timeout) { 
    // go to advanced 
    $state.transitionTo('post', {post: 2}); 
    // after 500ms switch to basic 
    $timeout(function() { 
     $state.transitionTo('post.basic', {post: 2}); 
    }, 500) 
} 
+0

谢谢,但是当我做这个改变时,我在控制台中得到了“Uncaught object”。 – ThinkingInBits

+0

@ThinkingInBits更新的答案,我基本上从你复制它,你的参数名称在uri和你实际传递的应该匹配。 – vittore

+0

哎呀,那只是一个错字。他们在我的代码中匹配。 – ThinkingInBits

1

这是AngularJS非常有用,

您可以指定动态路由与相同的URL模式多状态

我的代码遵循能对您有用,

Module Intialization,

var app = angular.module("koops_app", ['ui.router','ui.bootstrap']); //here you have to define all your required module for your project that you should inject... 

此外,

app.config(function ($locationProvider, $httpProvider, $stateProvider, $urlRouterProvider, $wampProvider) { 


    // When No Routing i.e Default Routing 
    $urlRouterProvider.when('', '/dashboard'); 


    // 404 
    $stateProvider.state("404", { 
     url: "/404", 
     templateUrl: 'template/404.html', 
    }); 


    // When Only One Argument i.e. Only Module Name 
    $stateProvider.state("default", { 
     url: "/:section", 
     templateUrl: 'views/View-to-be-load.html', //can use $stateParams.section for dynamic 
     reload: true, 
     resolve: { 
      loadController: ['$q', '$stateParams', '$state', 
         function ($q, $stateParams, $state) { 
          var deferred = $q.defer(); 
          deferred.resolve(); 
          return deferred.promise; 
         } 
        ] 
     }, 
     controllerProvider: function ($stateParams) { 
      return 'controllerName'; 
     } 
    }); 



     // When Two Argument i.e. Module/Controller 
     $stateProvider.state("default/title", { 
      url: "/:section/:title", 
      templateUrl: 'views/View-to-be-load.html', //can use $stateParams.section for dynamic 
      reload: true, 
      resolve: { 
       loadController: ['$q', '$stateParams', '$state', 
          function ($q, $stateParams, $state) { 
           var deferred = $q.defer(); 
           deferred.resolve(); 
           return deferred.promise; 
          } 
         ] 
      }, 
      controllerProvider: function ($stateParams) { 
       return 'controllerName'; 
      } 
     }); 



     // When Three Arguments i.e. Module/Controller/id 
     $stateProvider.state("default/title/id", { 
      url: "/:section/:title/:id", 
      templateUrl: 'views/View-to-be-load.html', //can use $stateParams.section for dynamic 
      reload: true, 
      resolve: { 
       loadController: ['$q', '$stateParams', '$state', 
          function ($q, $stateParams, $state) { 
           var deferred = $q.defer(); 
           deferred.resolve(); 
           return deferred.promise; 
          } 
         ] 
      }, 
      controllerProvider: function ($stateParams) { 
       return 'controllerName'; 
      } 
    }); 



     // Otherwise 
     $urlRouterProvider.otherwise("/404"); 

可能这是对你有帮助... 享受...

+0

这不回答问题。你的URL模式与每个状态定义不同。我的用例是,如果你在多个状态下使用“/:section”作为你的url模式。 – ThinkingInBits

+0

我可以看到你的答案在两个或多个不同的$ stateProvider.state()条目下使用相同的URL吗? –

+0

是的,它使用相同的url在不同的状态,但具有相同的patern @CodeUniqueelyly –

-1

为什么你会希望有映射到相同的URL两种不同的观点。当用户想要在其中一个州添加书签时,您是否想到了这个问题?那么如果他们具有完全相同的网址,您怎么知道哪一个是?

我建议定义就像两个不同的状态:

  • /:后 - 很简单视图
  • /:交/高级 - 针对高级视图

这是可以做到将/:post定义为抽象状态和简单和高级视图的两种不同状态。为了方便,简单的视图将作为默认值。如果您喜欢这个创意,我可以为您提供一个示例解决方案。

另一种选择是添加URL参数,例如:

  • /:后 - 很简单视图
  • /:后视=先进

我希望这个?答案会帮助你。至少从不同的角度看待事物;)。

+0

它是关于一个url模式,而不是一个url –

+0

谢谢你的洞察力。我们对这些路由名称有特定的要求和逻辑。用户不能简单地为这些URL之一添加书签......事实上,如果他们试图通过地址栏直接导航到这里,它们将被重定向到一个单独的视图/控制器。然而,我当时确实需要能够区分相同URL模式的控制器和视图。 – ThinkingInBits

相关问题