EmberJS - 为不同的路由共享控制器/模板 [英] EmberJS - sharing a controller / template for different routes
问题描述
我有一个非常简单的 CRUD 应用程序,它允许创建和编辑新对象.
用于添加记录和编辑记录的模板几乎相同.
它们使用完全相同的表单元素.唯一的区别是表单下方的标题和按钮(应该更新或创建记录)
在我的实现中,我有
- 2 个路由定义
- 2 个路由对象
- 2 个控制器对象
- 2 个模板
我想知道是否
- 我不能在这里提倡重复使用
- 如果需要所有这些对象.
困扰我的是什么:
- 我有 2 个单独的模板用于创建和编辑(虽然它们几乎相同)
- 我有 2 个独立的控制器,它们的作用完全相同.
我希望在控制器级别解决这个问题.当控制器装饰模型时,在我的情况下,单个控制器对象可以包装新记录或现有记录.然后它可以公开一个属性 (isNewObject),以便模板可以决定我们是处于新建"还是编辑"流程中.控制器可以有一个在 new
和 update
场景中都有效的 createOrUpdate 方法.
路线
当前的实现是为我的资源使用一个新的和一个编辑路由.
this.resource("locations", function(){this.route("new", {path:"/new"});this.route("edit", {path: "/:location_id" });});
新路线
new route
负责创建新记录,并在用户导航到新记录屏幕时调用.
App.LocationsNewRoute = Ember.Route.extend({模型:函数(){返回 App.Location.createRecord();}});
编辑路线
edit route
负责在用户单击概览屏幕中的编辑按钮时编辑现有对象.我没有扩展默认的编辑路线,而是使用自动生成的路线.
控制器
new
和 edit
控制器负责处理模板中发生的操作(保存或更新记录)
两个控制器唯一要做的就是提交事务.
注意:我想这是一个可以重复使用的候选者,但是我如何使用单个控制器来驱动 2 个不同的路线/模板?
App.LocationsNewController = Ember.ObjectController.extend({添加项目:功能(位置){location.transaction.commit();this.get("target").transitionTo("locations");}});App.LocationsEditController = Ember.ObjectController.extend({更新项目:功能(位置){location.transaction.commit();this.get("target").transitionTo("locations");}});
模板:
如您所见,我在这里唯一的代码重用是部分(模型字段绑定).我还有 2 个控制器(新建和编辑)和 2 个模板.
新模板设置正确的标题/按钮并重新使用表单部分.
编辑模板设置正确的标题/按钮并重新使用表单部分.
部分
注意:我希望我可以在这里做一些更高效/更智能的事情.
我希望我的模板看起来像这样:(从控制器获取标题,并有一个处理更新和创建的单一操作)
问题
我是否可以重新编写此代码以获得更多代码重用,或者尝试使用单个模板和单个控制器来实现编辑记录"和新记录"流是否是一个坏主意.如果是这样,如何做到这一点?我错过了我的 2 个路由(创建和编辑)将重新使用相同的控制器/模板的部分.
你自始至终都是正确的.
你也可以在edit route
中使用新的控制器和模板.
你只需要做两件事.
首先在 edit route
的 renderTemplate
钩子中指定模板名称为新的.
App.LocationsEditRoute = Ember.Route.extend({设置控制器:功能(控制器,模型){this.controllerFor('locations.new').setProperties({isNew:false,content:model});},渲染模板:函数(){this.render('位置/新')}});
随着新模板的呈现,控制器也将是 newController
,并且您可以让操作指向 newController
中的事件.
如果你想改变标题和按钮文本,你可以将它们作为计算属性观察 isNew
属性.
希望这会有所帮助.
P.S:不要忘记在new route
setupController
中设置isNew属性为trueI have a very simple CRUD application that allows for creating new objects as well as editing them.
The template used for adding a record and editing a record are almost identical.
They use the exact same form elements. The only difference is the title and the button below the form (that should either update or create a record)
In my implementation, I have
- 2 route definitions
- 2 route objects
- 2 controller objects
- 2 templates
I was wondering if
- I can't promote re-use here
- if all of these objects are required.
What bothers me :
- I have 2 separate templates for create and edit (while they are almost identical)
- I have 2 separate controllers that do exactly the same thing.
I was hoping to solve this on the controller level.
As a controller decorates a model, in my case 1 single controller object could wrap either a new record or an existing record.
It could then expose a property (isNewObject) so that the template can decide if we are in the "new" or "edit" flow. The controller could have a single createOrUpdate method that works both in the new
and in the update
scenario.
Routes
The current implementation is using a new and an edit route for my resource.
this.resource("locations", function(){
this.route("new", {path:"/new"});
this.route("edit", {path: "/:location_id" });
});
The new route
The new route
is responsible for creating a new record and is called when the user navigates to the new record screen.
App.LocationsNewRoute = Ember.Route.extend({
model: function() {
return App.Location.createRecord();
}
});
The edit route
The edit route
is responsible for editing an existing object when the user clicks the edit button in the overview screen.
I haven't extended the default edit route but instead I'm using the auto generated one.
Controllers
The new
and edit
controllers are responsible for handling the action that occurs in the template (either saving or updating a record)
The only thing both controllers do is commit the transaction.
Note: I guess this is a candidate for re-use, but how can I use a single controller for driving 2 different routes / templates ?
App.LocationsNewController = Ember.ObjectController.extend({
addItem: function(location) {
location.transaction.commit();
this.get("target").transitionTo("locations");
}
});
App.LocationsEditController = Ember.ObjectController.extend({
updateItem: function(location) {
location.transaction.commit();
this.get("target").transitionTo("locations");
}
});
Templates :
As you can see, the only code-reuse I have here is the partial (the model field binding). I still have 2 controllers (new and edit) and 2 templates.
The new templates sets the correct title / button and re-uses the form partial.
<script type="text/x-handlebars" data-template-name="locations/new" >
<h1>New location</h1>
{{partial "locationForm"}}
<p><button {{action addItem this}}>Add record</button></p>
</script>
The edit templates sets the correct title / button and re-uses the form partial.
<script type="text/x-handlebars" data-template-name="locations/edit" >
<h1>Edit location</h1>
{{partial "locationForm"}}
<p><button {{action updateItem this}}>Update record</button></p>
</script>
The partial
<script type="text/x-handlebars" data-template-name="_locationForm" >
<form class="form-horizontal">
<div class="control-group">
<label class="control-label" for="latitude">Latitude</label>
<div class="controls">
{{view Ember.TextField valueBinding="latitude"}}
</div>
</div>
<div class="control-group">
<label class="control-label" for="latitude">Longitude</label>
<div class="controls">
{{view Ember.TextField valueBinding="longitude"}}
</div>
</div>
<div class="control-group">
<label class="control-label" for="accuracy">Accuracy</label>
<div class="controls">
{{view Ember.TextField valueBinding="accuracy"}}
</div>
</div>
</form>
</script>
Note: I would expect that I can do something efficient/smarter here.
I would want my template to look this this : (getting the title from the controller, and have a single action that handles both the update and the create)
<script type="text/x-handlebars" data-template-name="locations" >
<h1>{{title}}</h1>
{{partial "locationForm"}}
<p><button {{action createOrUpdateItem this}}>Add record</button></p>
</script>
Question
Can I re-work this code to have more code-reuse, or is it a bad idea to attempt to do this with a single template and a single controller for both the "edit record" and "new record" flows. If so, how can this be done ? I'm missing the part where my 2 routes (create and edit) would re-use the same controller / template.
You were correct throughout.
And you can use the new controller and template in edit route
also.
You have to do only two things.
First give the template name as new in the renderTemplate
hook of edit route
.
App.LocationsEditRoute = Ember.Route.extend({
setupController: function(controller, model) {
this.controllerFor('locations.new').setProperties({isNew:false,content:model});
},
renderTemplate: function() {
this.render('locations/new')
}
});
As the new template is rendered the controller also will be newController
, and you can have the action to point to an event in the newController
.
If you want to change the title and button text, you can have them as computed properties observing isNew
property.
Hope this helps.
P.S: Don't forget to set the isNew property to true in the setupController
of new route
这篇关于EmberJS - 为不同的路由共享控制器/模板的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!