intercellular / cell

A self-driving web app framework
https://www.celljs.org
MIT License
1.5k stars 94 forks source link

The second cell will remove after I start typing #1

Closed zevenbergm closed 7 years ago

zevenbergm commented 7 years ago

First of all, it's a brilliant celljs is a brilliant concept. I love it!

At the moment I face a little issue. I've created the following page with two cells:

<script>
        editTodo = {
            $cell:true, $type: 'body', style: 'padding:30px',
            $components: [
                {
                    $type: 'div', $text: 'Enter todo:'
                },
                { 
                    $type: 'input', 
                    onkeyup: function(e) { 
                        if (e.keyCode === 13) {

                            document.getElementById('#list')._add("{ title: '" + (this.value) + "'}");

                            this.value = "";
                        }
                    }
                }
            ]
        }

        listTodo = {
            $cell:true, $type: 'ul', id: 'list', _todos: [],
            $components: [],
            _add: function (todo) {
                this._todos.push(todo);
            },
            $update: function() {
                this.$components = this._todos.map(function(todo){
                    return { $type: "li", $text: todo.title }
                })
            }
        }

    </script>

However, the second cell (listTodo) will be removed if I start typing in the textbox. Can you help me in solving this issue.

BTW, I'm working with Chrome.

Best regards, Martin Zevenbergen

gliechtenstein commented 7 years ago

I just tried it out and I see three problems:

  1. You're passing a JSON string to the _add function but you really don't need to. You can simply pass the object itself.
  2. you're using getElementById but passing a selector #list (I've been there too :) ) You should be either doing document.getElementById('list') or document.querySelector('#list')
  3. Also the first cell element is a $type: "body", which is causing the problem. Whenever you declare a cell, here's what happens:

A. See if it's either $type: body, $type: head, or contains an id. If any of these is true, Cell replaces these existing elements with the generated HTML element. B. Otherwise it creates a new HTML element and appends it to the body.

So in your case you first declared $type: "body" so it replaces it with the existing body element, but you also declare the second variable which is a ul which tries to get appended to the body. This confuses Cell because you're trying two different methods at once. You should either be either:

  1. declaring the first cell as a $type: "div" (or anything other than body really) - this will make sure both cells get created and appended into existing body, avoiding the confusion
  2. or add listTodo as one of the components of the body so there's no confusion as well.

Here's an example of the former:

<html>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://www.celljs.org/cell.js"></script>
<script>
editTodo = {
  $cell:true, $type: 'div', style: 'padding:30px',
  $components: [
    {
      $type: 'div', $text: 'Enter todo:'
    },
    { 
      $type: 'input', 
      onkeyup: function(e) { 
        if (e.keyCode === 13) {

          document.getElementById('list')._add({ title: this.value});

          this.value = "";
        }
      }
    }
  ]
}

listTodo = {
  $cell:true, $type: 'ul', id: 'list', _todos: [],
  $components: [],
  _add: function (todo) {
    this._todos.push(todo);
  },
  $update: function() {
    this.$components = this._todos.map(function(todo){
      return { $type: "li", $text: todo.title }
    })
  }
}
</script>
</html>

Here's the latter:

<html>
<meta name="viewport" content="width=device-width, initial-scale=1">
<script src="https://www.celljs.org/cell.js"></script>
<script>
listTodo = {
  $type: 'ul', id: 'list', _todos: [],
  $components: [],
  _add: function (todo) {
    this._todos.push(todo);
  },
  $update: function() {
    this.$components = this._todos.map(function(todo){
      return { $type: "li", $text: todo.title }
    })
  }
}
inputTodo = { 
  $type: 'input', 
  onkeyup: function(e) { 
    if (e.keyCode === 13) {

      document.getElementById('list')._add({ title: this.value});

      this.value = "";
    }
  }
}
labelTodo = {
  $type: 'div', $text: 'Enter todo:'
} 

editTodo = {
  $cell:true, $type: 'body', style: 'padding:30px',
  $components: [ labelTodo, inputTodo, listTodo ]
}

</script>
</html>

Hope this helps! Let me know if you have further questions!

zevenbergm commented 7 years ago

Thanks for the prompt response! Much appreciated! It's working right now! I can continue my celljs journey! ;-)