0

I have a problem with konvajs. I have a konva Stage that I clone into a temporary Stage, so I can revert changes made by a user, when the user cancels. The way I do this is, that I clone the existing Stage into a temporary one, destroy the children of the origin and after that I move the children of the temporary Stage back to the original and destroy the temporary Stage. The problem is, when I try to access the children now, for example via findOne('#id-of-child'), I get undefined, even though the children exist.

Here's what I've done so far:

clone: function()
{
  var cloned_stage = this.stage.clone();

  Array.each(this.stage.getChildren(), function(layer, lidx) {
    if (layer.attrs.id) {
      // setting the id to the ones, the children had before
      cloned_stage.children[lidx].attrs.id = layer.attrs.id;
    }
  });
  return cloned_stage;
},

restore: function(tmp_stage)
{
  this.stage.destroyChildren();

  Array.each(tmp_stage.getChildren(), function(layer, lidx) {
    var tmp_layer = layer.clone();
    tmp_layer.attrs.id = layer.attrs.id;
    tmp_layer.moveTo(this.stage);
  }.bind(this));
  tmp_stage.destroy();
  this.stage.draw();
},

Now when the user opens the toolbox to change something, the current stage is cloned with the "clone" function and when the user cancels his changes, the "restore" function is called with the cloned stage as parameter. But after that when I try to do things like the following they do not work as expected.

some_child_of_the_stage.getLayer();      ->     returns null 
var edit_layer = this.stage.findOne('#edit-layer');     ->    returns undefined

But the "some_child_of_the_stage" does exist and has a layer of course and the stage has a child with the id "edit-layer".

Me and my colleague are at our wit's end.

I appreciate any help and suggestions thank you.

Update: A short fiddle showing the problem via console.log: fiddle

GiftZwergrapper
  • 2,602
  • 2
  • 20
  • 40

1 Answers1

1
  1. It is better not to touch attrs property of a node and use public getters and setters.

  2. Konva has special logic for storing id property. Selector by id #edit-layer may not work because of direct access to attrs id.

  3. You can use name property fo that case.

https://jsfiddle.net/s36hepvg/12/

lavrton
  • 18,973
  • 4
  • 30
  • 63
  • 1
    This solves the problem for `this.stage.findOne('#edit-layer');` but the problem with the `getLayer()` function still exists. It just seems like there is some caching or something, because when I clone the stage, the elements on it still output the same id when I add a click event which outputs via `console.log()`. – GiftZwergrapper Aug 30 '16 at 09:56
  • Can you add a demo? – lavrton Aug 31 '16 at 04:30
  • layer is null here, because you called `stage.destroyChildren();`. `destroy` function will clear all inner references and parent-child relationships. – lavrton Sep 01 '16 at 10:52
  • 1
    Yes, but I have cloned `this.stage` to `tmp_stage` before calling `this.stage.destroyChildren()` and afterwards I am moving the layers from `tmp_stage` back to `this.stage`. I don't really understand why destroying the children of `this.stage` has this effect in this approach. – GiftZwergrapper Sep 01 '16 at 11:16
  • You are calling `rect.getLayer()`, but `rect` is a reference to destroyed node. – lavrton Sep 02 '16 at 06:28
  • I am also attempting to clone a stage, then access the cloned stage's children, but they are shown in the object, but when trying to access, they are undefined. `var clonedStage = stage.clone();console.log(clonedStage.findOne('#documentLayer'));` Seems basic to me, but doesn't actually work. I'm not calling any destroy methods. – stwhite Nov 03 '19 at 19:07