2013-04-08 27 views
6

Tôi đang tạo tiện ích con nhận xét có thể sử dụng lại (loại đa hình). Tôi muốn một nút cho phép tôi quay lại tuyến đường chính (ví dụ: nếu tôi ở/blog_posts/1/nhận xét, tôi muốn nút đưa tôi quay lại/blog_posts/1).Tìm tuyến đường mẹ ở EmberJS

Tôi hiện đang sử dụng transitionToRoute('blog_post'), nhưng điều này sẽ không hoạt động trong thời gian dài vì tôi muốn mã này chạy chung với bất kỳ mô hình nào (tức là nó sẽ không biết gì về tên của tuyến đường, vì vậy tôi không thể gọi 'blog_post'). Tôi đoán tôi đang tìm kiếm một trong hai thứ như Rails 'url_for hoặc một cách để nói router.get('parent_route') (hoặc controller.get('parent_route')).

Bất kỳ con trỏ hoặc ý tưởng nào? Cảm ơn.

Trả lời

10

này được trả lời trong năm 2013 cho v0.9.8 ember hoặc một cái gì đó, khuôn khổ đã đi một chặng đường dài kể từ đó. Tôi nghĩ rằng có thể có một giải pháp tốt hơn nhiều với phiên bản hiện tại của khung công tác. Vì tôi không liên lạc với Ember, thật sự không thể cập nhật câu trả lời này!

Lấy cảm hứng từ một chức năng riêng trong mã nguồn, Thêm phương pháp sau đây để các tuyến đường mà trả về tên của parentRoute

Ember.Route.reopen({ 
    getParentRoute: function(){ 
    var route = this; 
    var handlerInfos = route.router.router.currentHandlerInfos; 
    var parent, current; 

    for (var i=0, l=handlerInfos.length; i<l; i++) { 
     current = handlerInfos[i].handler; 
     if((current.routeName == route.routeName)||(current.routeName.match(/./) && current.routeName.split('.')[1] == route.routeName)){ 
     return parent.routeName; 
     } 
     parent = current; 
    } 
    } 
}) 

Sử dụng bên trong các tuyến đường như sau

App.SomeRoute = Ember.Route.extend({ 
    events: { 
    goBack: function(){ 
     this.transitionTo(this.getParentRoute()); 
    } 
    } 
}) 

tay lái

<script type="text/x-handlebars" data-template-name="some"> 
    <a href="#" {{action goBack}}>Back</a> 
</script> 

Đối với mã thực tế, o bút this và làm một tổ hợp phím CTRL + F để function parentRoute

+0

Câu trả lời hay - cảm ơn bạn. Tôi đã thực hiện điều này và nó hoạt động một điều trị! – iHiD

+1

Lưu ý rằng bạn không thể sử dụng điều này để lấy tuyến đường mẹ của tuyến đường hiện đang được chuyển sang (ví dụ: khi trang đang được tải) vì currentHandlerInfos có thể không được đặt. Tôi đã cố gắng sử dụng điều này trong một lớp cơ sở xử lý tuyến đường để có được mô hình của cha mẹ mà không biết tên của nó, tiếc là tải trang quá sớm để làm như vậy. –

+0

Vì vậy, đây là cách tốt để có được tên tuyến đường mẹ của tuyến đường CURRENT, và không phải của đối tượng tuyến mà từ đó phương thức được gọi. Đó là bởi vì bạn đang nhận được thứ bậc của các tuyến đường thông qua 'bộ định tuyến'. – Huafu

6

Bạn có thể sử dụng mẫu chung {{action }} trong mẫu của mình nhưng có thông tin cụ thể về "quay lại" được triển khai trong bộ định tuyến. Điều này hoạt động vì Ember bubbles up sự kiện goBack trước tiên cho bộ điều khiển, sau đó là tuyến hiện tại, sau đó là tuyến đường mẹ, v.v. cho đến khi xử lý hành động được tìm thấy. Trong trường hợp này, không có hành động nào phù hợp trên bộ điều khiển, do đó nó được xử lý bởi tuyến hiện tại. Điều này giữ cho template/view/controller của bạn bất khả tri đối với các chi tiết cụ thể, nhưng khi bạn đang hooking lên widget, bạn có thể chỉ định cách xử lý "quay lại".

Trong ví dụ cùng một nút làm cho lộ trình để chuyển sang tuyến đường khác nhau tùy thuộc vào tuyến đường là các tuyến đường hiện tại:

  • trong lộ trình /posts các hiệu ứng chuyển tiếp nút quay lại để /
  • trong lộ trình /posts/new lại nút chuyển tiếp để /posts

JSBin example

Javascript:

App = Ember.Application.create({}); 

App.Router.map(function() { 
    this.resource('posts', function() { 
    this.route('new'); 
    }); 
}); 

App.PostsRoute = Ember.Route.extend({ 
    events: { 
    goBack: function(){ 
     this.transitionTo('index'); 
    } 
    } 
}); 

App.PostsNewRoute = Ember.Route.extend({ 
    events: { 
    goBack: function(){ 
     this.transitionTo('posts'); 
    } 
    } 
}); 

mẫu:

<script type="text/x-handlebars" data-template-name="index"> 
    <h2>Index Content:</h2> 
    {{#linkTo posts}}Posts{{/linkTo}} 
    {{outlet}} 
</script> 

    <script type="text/x-handlebars" data-template-name="posts"> 
    <h2>Posts</h2> 
    <button {{action goBack}}>Go back</button> 
    {{#linkTo posts.new}}New{{/linkTo}} 
    {{outlet}} 
    </script> 

    <script type="text/x-handlebars" data-template-name="posts/new"> 
    <h2>Posts/New</h2> 
    </script> 
+0

Great câu trả lời - cảm ơn! Tôi đã đánh dấu @ Unspecified's như được chấp nhận bởi vì nó sẽ liên quan đến việc thiết lập ít hơn cho mỗi tuyến mới mà tôi thêm - nhưng điều này sẽ là một triển khai hoàn hảo tốt, vì vậy cảm ơn :) – iHiD

+0

Tôi nghĩ rằng điều này có thể được thực hiện trên Ember.Route lớp chính nó, tự động thêm phương thức goBack trong khi khởi tạo tuyến đường. Điều này cũng sạch hơn nhiều. –

3

Dựa trên chì và rà soát các nguồn v1.5 Ember tôi sử dụng sau Mudasi Ali:

Coffeescript (sử dụng coffeescript.org để transpile nếu bạn muốn JS/ES):

Ember.Route.reopen 
    parentRoute: Em.computed -> 
    r = @router.router 
    if r.currentTransition 
     handlerInfos = r.currentTransition.state.handlerInfos 
    else 
     handlerInfos = r.state.handlerInfos 

    handlerInfos = this.router.router.state.handlerInfos 
    return unless handlerInfos 

    parent = @ 
    for info in handlerInfos 
     break if info.handler == @ 
     parent = info.handler 
    parent 

    parentRouteName: Em.computed.alias('parentRoute.routeName') 

    parentController: -> 
    @controllerFor @get('parentRouteName') 

    parentModel: -> 
    @modelFor @get('parentRouteName') 

trên đây cung cấp các thuộc tính parentRouteparentRouteName, trên tất cả các tuyến đường của bạn và hai chức năng tiện dụng parentController()parentModel() mà trả lại bộ điều khiển phụ huynh và mô hình tương ứng có thể hữu ích cho nhiều tình huống, đặc biệt nếu bạn đại diện cho việc chỉnh sửa tài nguyên dưới dạng một tuyến đường lồng nhau.

Bạn cũng có thể xác định một số hành động để sử dụng trong quan điểm của bạn/điều khiển vv cho hủy/trở lại xử lý như sau:

Ember.Route.reopen 
    actions: 
    goBack: -> 
     @transitionTo @get('parentRouteName') 

Nếu bạn có một hệ thống phân cấp định tuyến sâu và muốn nói bỏ qua một con đường trung gian, bạn chỉ cần ghi đè GoBack như sau:

App.SomeIntermediateRouteToSkipOnBack = Em.Route.extend 
    actions: 
    goBack: -> 
     # skip the immediate parent and use the grandparent route 
     @transitionTo @get('parentRoute.parentRouteName) 
3

Cập nhật cho Ember 2,6 trong tập tin app/initializers/parent_route.js

import Ember from 'ember'; 

var alreadyRun = false; 

export default { 
    name: 'parent-route', 
    initialize: function() { 
    if (alreadyRun) { 
     return; 
    } else { 
     alreadyRun = true; 
    } 
    Ember.Route.reopen({ 
     parentRoute: Ember.computed(function() { 
     let handlerInfos, i, info, len, parent, r; 
     r = this.router.router; 
     if (r.activeTransition) { 
      handlerInfos = r.activeTransition.state.handlerInfos; 
     } else { 
      handlerInfos = r.state.handlerInfos; 
     } 
     if (!handlerInfos) { 
      return; 
     } 
     parent = this; 
     for (i = 0, len = handlerInfos.length; i < len; i++) { 
      info = handlerInfos[i]; 
      if (info.handler === this) { 
      break; 
      } 
      parent = info.handler; 
     } 
     return parent; 
     }), 
     parentRouteName: Ember.computed.alias('parentRoute.routeName'), 

     parentController: Ember.computed(function() { 
     return this.controllerFor(this.get('parentRouteName')); 
     }), 

     parentModel: Ember.computed(function() { 
     return this.modelFor(this.get('parentRouteName')); 
     }) 
    }); 

    } 
}; 

Trong các tuyến đường của bạn, bạn có thể truy cập vào parentcontroller như this.get('parentController') và mô hình như this.get('parentModel')

Các vấn đề liên quan