Javascript Meteor JS:存储特定模板实例状态的最佳方法是什么?
我正在学习Meteor JS中的会话和反应数据源。它们非常适合设置全局UI状态。但是,我不知道如何将它们限定到模板的特定实例 以下是我正在尝试做的 我在一个页面上有多个contenteditable元素。每个按钮下面都有一个“编辑”按钮。当用户单击编辑按钮时,它应该关注元素,并显示“保存”和“取消”按钮 如果用户单击“取消”,则任何更改都将被消除,模板实例应使用原始内容重新提交 这是我目前掌握的代码Javascript Meteor JS:存储特定模板实例状态的最佳方法是什么?,javascript,meteor,Javascript,Meteor,我正在学习Meteor JS中的会话和反应数据源。它们非常适合设置全局UI状态。但是,我不知道如何将它们限定到模板的特定实例 以下是我正在尝试做的 我在一个页面上有多个contenteditable元素。每个按钮下面都有一个“编辑”按钮。当用户单击编辑按钮时,它应该关注元素,并显示“保存”和“取消”按钮 如果用户单击“取消”,则任何更改都将被消除,模板实例应使用原始内容重新提交 这是我目前掌握的代码 // Helper Template.form.helpers({ editState: f
// Helper
Template.form.helpers({
editState: function() {
return Session.get("editState");
}
});
// Rendered
Template.form.rendered = function(e){
var $this = $(this.firstNode);
var formField = this.find('.form-field');
if (Session.get("editState")) formField.focus();
};
// Event map
Template.form.events({
'click .edit-btn' : function (e, template) {
e.preventDefault();
Session.set("editState", "is-editing");
},
'click .cancel-btn' : function (e, template) {
e.preventDefault();
Session.set("editState", null);
},
});
// Template
<template name="form">
<div class="{{editState}}">
<p class="form-field" contenteditable>
{{descriptionText}}
</p>
</div>
<a href="#" class="edit-btn">Edit</a>
<a href="#" class="save-btn">Save</a>
<a href="#" class="cancel-btn">Cancel</a>
</template>
// CSS
.edit-btn
.cancel-btn,
.save-btn {
display: inline-block;
}
.cancel-btn,
.save-btn {
display: none;
}
.is-editing .cancel-btn,
.is-editing .save-btn {
display: inline-block;
}
//助手
Template.form.helpers({
editState:函数(){
return Session.get(“editState”);
}
});
//渲染
Template.form.rendered=函数(e){
var$this=$(this.firstNode);
var formField=this.find('.formField');
if(Session.get(“editState”))formField.focus();
};
//事件图
Template.form.events({
“单击。编辑btn”:函数(e,模板){
e、 预防默认值();
Session.set(“editState”,“正在编辑”);
},
“单击。取消btn”:函数(e,模板){
e、 预防默认值();
Session.set(“editState”,null);
},
});
//模板
{{descriptionText}}
//CSS
.编辑btn
.取消btn,
.保存btn{
显示:内联块;
}
.取消btn,
.保存btn{
显示:无;
}
.正在编辑。取消btn,
.正在编辑。保存btn{
显示:内联块;
}
问题
如果我有多个
表单
模板的实例,那么.Form字段
将为每个实例聚焦,而不仅仅是正在编辑的实例。如何使被编辑的模板聚焦?您可以使用数据呈现模板,这基本上只是插入页面时传递给模板的对象
数据可能只是会话
中编辑状态
使用的关键
例如,使用template.form({editStateKey:'editState-topForm'})呈现模板
你可以做一个把手助手,例如
Handlebars.registerHelper('formWithOptions',
function(editStateKey){
return Template.form({editStateKey:editStateKey})
});
然后将其插入到模板中,并使用
{{{formWithOptions'editState topForm'}}}
(注意三元组{
,}
)
接下来,将引用从Session.x('editState')
更改为Session.x(this.editStateKey)
/Session.x(this.data.editStateKey)
注意:如果您使用的是iron router
,它有额外的api用于将数据
传递到模板
注2:在Meteor1.0中,应该有更好的支持来编写自己的小部件。这应该可以更好地控制这类事情。作为一项政策,我几乎在所有情况下都避免会话。我觉得随着应用程序的增长,它们的全球范围会导致坏习惯和缺乏关于分离关注点的良好规范。此外,由于会话的全局作用域,在呈现模板的多个实例时,会话可能会导致问题。出于这些原因,我觉得其他方法更具可扩展性
替代办法
1 addClass/removeClass
您可以直接执行所需的操作,而不是设置一个状态然后在其他地方对其作出反应。此处,类根据需要显示和隐藏块:
'click .js-edit-action': function(event, t) {
var $this = $(event.currentTarget),
container = $this.parents('.phenom-comment');
// open and focus
container.addClass('editing');
container.find('textarea').focus();
},
'click .js-confirm-delete-action': function(event, t) {
CardComments.remove(this._id);
},
2范围为模板实例的ReactiveVar
3铁路由器的状态变量
得到
设置
4收集数据
另一种方法是简单地通过更新集合中的数据来声明。有时候,这很有道理
5更新数据上下文
在我看来,会话往往是更糟糕的选择。此外,我个人不使用#3,因为我觉得如果我们想切换到另一个路由器包(如“Flow”)时,与iron router的联系越少越好。谢谢,我对editState topform
的来源有点困惑。我刚刚偶然发现了一个类似问题的解决方案,它采用将模板实例的id放入会话对象的方法。这个答案是假设您正在重新使用表单
模板,并且每次都需要使用不同的选项(即要使用的会话
的名称)对其进行实例化。如果使用不同的模板,但一次只需要一个可编辑的模板。更好的解决方案是将活动的“模板”存储在会话变量中。
'click .js-edit-action': function(event, t) {
var $this = $(event.currentTarget),
container = $this.parents('.phenom-comment');
// open and focus
container.addClass('editing');
container.find('textarea').focus();
},
'click .js-confirm-delete-action': function(event, t) {
CardComments.remove(this._id);
},
if (Meteor.isClient) {
Template.hello.created = function () {
// counter starts at 0
this.counter = new ReactiveVar(0);
};
Template.hello.helpers({
counter: function () {
return Template.instance().counter.get();
}
});
Template.hello.events({
'click button': function (event, template) {
// increment the counter when button is clicked
template.counter.set(template.counter.get() + 1);
}
});
}
Router.route('/posts/:_id', {name: 'post'});
PostController = RouteController.extend({
action: function () {
// set the reactive state variable "postId" with a value
// of the id from our url
this.state.set('postId', this.params._id);
this.render();
}
});
Template.Post.helpers({
postId: function () {
var controller = Iron.controller();
// reactively return the value of postId
return controller.state.get('postId');
}
});