component / reactive

Tiny reactive template engine
382 stars 48 forks source link

How to update an array? #131

Closed pakastin closed 10 years ago

pakastin commented 10 years ago

How do I update an array?

I mean:

var model = {
  numbers: [1,4,3]
}
 , template = '<ul><li each="numbers">{this}</li></ul>'
 , view = reactive(template, model)

document.body.appendChild(view)

view.set('numbers[1]', 2)

or:

view.set('numbers.1', 2)

Nothing happens :/

If I do:

view.set('numbers', [1,2,3])

All of the items update, which is not what I want.. I know this by test:

template = '<ul><li each="numbers">{this} {Date()}</li></ul>'

-->

1 Sat Apr 19 2014 14:11:03 GMT+0300 (EEST)
2 Sat Apr 19 2014 14:11:03 GMT+0300 (EEST)
3 Sat Apr 19 2014 14:11:03 GMT+0300 (EEST)

should be something like:

1 Sat Apr 19 2014 14:10:58 GMT+0300 (EEST)
2 Sat Apr 19 2014 14:11:03 GMT+0300 (EEST)
3 Sat Apr 19 2014 14:10:58 GMT+0300 (EEST)
chemzqm commented 10 years ago

Reactive just listening to change events emitted by the model to update the view correspondingly. The array in the each statement is considered as one property, and the corresponding view could only be updated as a whole. If you need something like the date keep unchanged, you can assign the date as a property to the object in the array.

The each attribute in reactive is lightweight, so it's not that clever as AngularJS. For the reactive of a list of models, I use the list to do that, which is quite opinionated.

defunctzombie commented 10 years ago

Changing just one item is actually simple. Just use splice on the original array.

model.numbers.splice(1, 1, 2);

The reason you need to use splice versus .set or changing the index using [] notation directly is because the each binding intercepts these array calls splice, push, etc and updates the view accordingly. No need for complex event emitters.