Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/406.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript Meteor反应嵌套对象更新父对象_Javascript_Meteor - Fatal编程技术网

Javascript Meteor反应嵌套对象更新父对象

Javascript Meteor反应嵌套对象更新父对象,javascript,meteor,Javascript,Meteor,我试图让一个javascript对象成为被动对象,这样当一个子对象被更新时,原始(父)对象就会被更新——无论是在视图中还是在javascript中 这几乎可以做到,除了单击“完成”按钮时,console.log输出仅在第一次时准确。之后,正确地切换任何子项都会更新视图,但底层javascript不会更新,因为子项的“选定”值不再正确 此外,我希望能够简化,并在任何子项被切换为选中或未选中时,简单地更新父项项对象 我来自AngularJS,这要简单得多——如果传入一个对象,然后更新该对象的属性,那

我试图让一个javascript对象成为被动对象,这样当一个子对象被更新时,原始(父)对象就会被更新——无论是在视图中还是在javascript中

这几乎可以做到,除了单击“完成”按钮时,console.log输出仅在第一次时准确。之后,正确地切换任何子项都会更新视图,但底层javascript不会更新,因为子项的“选定”值不再正确

此外,我希望能够简化,并在任何子项被切换为选中或未选中时,简单地更新父项
对象

我来自AngularJS,这要简单得多——如果传入一个对象,然后更新该对象的属性,那么父属性也会更新,并自动保持同步

似乎
this
和数据上下文是getter而不是setter
Template.currentData()
似乎相关,但我一直无法使其正常工作:

我获取要更新的项的方法是通过设置和比较索引来手动更新它,以从内部子数据上下文更新主父对象,但这同样不理想,并且随着嵌套的增加而变得越来越混乱,因为我需要所有嵌套的索引能够回溯到主
对象覆盖整个内容以强制更新。

长话短说,我希望给定的数据上下文(来自一个事件)能够成为一个setter,这样,如果我在一个{{each}中,恰好在项[1]上。子项[2],那么我就可以执行
this.selected=!这个。选择了
,然后将有效地更新
项[1]。子项[2]。选择了
(反应性地更新javascript对象本身和DOM)。因此,稍后我可以检查
项[1]的值。子项[2]。选中的
,并知道它是可靠和准确的。目前,我正在根据所选的
布尔值更新DOM,但是父
数组不准确

HTML/模板:

<template name="items">
  {{#each items}}
  <div class='item-title'>{{title}}</div>
  <div class='{{classes.cont}}'>
    {{#each subitem}}
      {{> subitems }}
    {{/each}}
  </div>
  {{/each}}

  <div class='btn btn-primary btn-block items-done'>Done?</div>
</template>

<template name="subitems">
  <div class='flexbox subitems'>
    <div class='flex1 pointer'>{{title}}</div>
    {{#if selected}}
    <div class='fa fa-check-circle'></div>
    {{else}}
    <div class='fa fa-plus-circle'></div>
    {{/if}}
  </div>
</template>

{{{#每项}
{{title}}
{{#每个子项}
{{>子项}
{{/每个}}
{{/每个}}
完成?
{{title}}
{{#如果选中}
{{else}
{{/if}
Javascript

if (Meteor.isClient) {
var items1 =[
  {
    title: 'Item 1',
    subitem: [
        {
            title: 'Sub 1.1'
        },
        {
            title: 'Sub 1.2'
        },
        {
            title: 'Sub 1.3'
        }
    ]
},
{
    title: 'Item 2',
    subitem: [
        {
            title: 'Sub 2.1'
        },
        {
            title: 'Sub 2.2'
        },
        {
            title: 'Sub 2.3'
        }
    ]
}
];

var ii, jj;
for(ii =0; ii<items1.length; ii++) {
items1[ii].classes ={
  cont: 'hidden'
};
items1[ii].index =ii;   //Blaze / Spacebars does not yet give access to index? Maybe @index in html but no equivalent in `this` in javascript?

for(jj =0; jj<items1[ii].subitem.length; jj++) {
  items1[ii].subitem[jj].selected =false;
  items1[ii].subitem[jj].index =jj;
}
}

Template.items.created =function() {
  this.items =new ReactiveVar;
  this.items.set(items1);
};

Template.items.helpers({
  items: function() {
    return Template.instance().items.get();
  }
});

Template.items.events({
'click .item-title': function(evt, template) {
var items =template.items.get();
    if(this.classes.cont ==='visible') {
      this.classes.cont ='hidden';
    }
    else {
      this.classes.cont ='visible';
      //hide all others
      for(ii =0; ii<items.length; ii++) {
      if(ii !==this.index) {
        items[ii].classes.cont ='hidden';
      }
    }
    }

    template.items.set(items);
},

  'click .items-done': function(evt, template) {
    console.log(template.items.get());    //TESTING
}

});

Template.subitems.created =function() {
this.selected =new ReactiveVar;
this.selected.set(this.data.selected);
};

Template.subitems.helpers({
selected: function() {
return Template.instance().selected.get();
}
});

Template.subitems.events({
'click .subitems': function(evt, template) {
//toggle selected
this.selected =!this.selected;
template.selected.set(this.selected);
}
});
}
if(Meteor.isClient){
变量项1=[
{
标题:“项目1”,
分项:[
{
标题:“Sub 1.1”
},
{
标题:“Sub 1.2”
},
{
标题:“Sub 1.3”
}
]
},
{
标题:“项目2”,
分项:[
{
标题:“Sub 2.1”
},
{
标题:“Sub 2.2”
},
{
标题:“Sub 2.3”
}
]
}
];
varⅡ,jj;
对于(ii=0;ii切换到一个(仅本地)集合似乎使它变得被动,我确实必须更新根(父)项(使用
Template.parentData()
)。 因此,基本上转换为集合并专门用作集合是可行的。有点恼人,似乎有点像黑客,但我想这就是meteor的目的,模糊了服务器和客户端之间的界限——只需将集合用于一切,让内置的meteor反应发挥其魔力

if(Meteor.isClient){
变量项1=[
{
标题:“项目1”,
分项:[
{
标题:“Sub 1.1”
},
{
标题:“Sub 1.2”
},
{
标题:“Sub 1.3”
}
]
},
{
标题:“项目2”,
分项:[
{
标题:“Sub 2.1”
},
{
标题:“Sub 2.2”
},
{
标题:“Sub 2.3”
}
]
}
];
varⅡ,jj;

对于(ii=0;ii)这可能很有趣。它是一个反应对象的实现-即一个具有单个依赖项但有多个键(和子键)的对象,可以自己显式获取或设置。@user728291-该链接交给apple developer。我认为解决方案已计划好,但不确定何时。非常好。我认为您的解决方法是合理的。感谢更新链接@user728291-因此,关键似乎是
.field()
设置子键并将其传播到顶级对象?
if (Meteor.isClient) {
var items1 =[
{
    title: 'Item 1',
    subitem: [
        {
            title: 'Sub 1.1'
        },
        {
            title: 'Sub 1.2'
        },
        {
            title: 'Sub 1.3'
        }
    ]
},
{
    title: 'Item 2',
    subitem: [
        {
            title: 'Sub 2.1'
        },
        {
            title: 'Sub 2.2'
        },
        {
            title: 'Sub 2.3'
        }
    ]
}
];

var ii, jj;
for(ii =0; ii<items1.length; ii++) {
items1[ii].classes ={
  cont: 'hidden'
};
items1[ii].index =ii;   //Blaze / Spacebars does not yet give access to index? Maybe @index in html but no equivalent in `this` in javascript?

for(jj =0; jj<items1[ii].subitem.length; jj++) {
  items1[ii].subitem[jj].selected =false;
  items1[ii].subitem[jj].index =jj;
}
}

ItemCollection = new Meteor.Collection(null);
for(ii =0; ii<items1.length; ii++) {
ItemCollection.insert(items1[ii]);
}

Template.items.helpers({
items: function() {
return ItemCollection.find();
}
});

Template.items.events({
'click .item-title': function(evt, template) {
var items =ItemCollection.find().fetch();
    if(this.classes.cont ==='visible') {
      this.classes.cont ='hidden';
    }
    else {
      this.classes.cont ='visible';
      //hide all others
      for(ii =0; ii<items.length; ii++) {
      if(ii !==this.index) {
        //items[ii].classes.cont ='hidden';
        ItemCollection.update(items[ii]._id, {$set: {classes: {cont: 'hidden'} } });
      }
    }
    }

    //update current item
    ItemCollection.update(this._id, {$set: {classes: {cont: this.classes.cont } } });
},

'click .items-done': function(evt, template) {
console.log(ItemCollection.find().fetch());    //TESTING
}

});


Template.subitems.events({
'click .subitems': function(evt, template) {
//toggle selected
this.selected =!this.selected;

var itemId =Template.parentData(1)._id;
var setObj ={};
setObj['subitem.'+this.index+'.selected'] =this.selected;
console.log(itemId+' '+JSON.stringify(setObj));   //TESTING
ItemCollection.update(itemId, { $set: setObj});
}
});
}