peerlibrary / meteor-blaze-components

Reusable components for Blaze
http://components.meteorapp.com/
BSD 3-Clause "New" or "Revised" License
354 stars 26 forks source link

how to create and destroy a component programmatically with javascript #75

Closed Alino closed 9 years ago

Alino commented 9 years ago

I am trying to remove the component if the user clicks on a button which is part of that components template.

  events: -> [
    'click .param-remove': @onRemove
  ]

  onRemove: (event) ->
    Blaze.remove @currentComponent()

it should remove itself, I expect the component to be removed from DOM. Unfortunately this doesn't work and gives this error:

Uncaught Error: Expected Template or View

I also would like to create a new component of the same type like this:

   events:  -> [
      'change input': @onChange
   ]

  onChange: (event) ->
    Blaze.render(Template.MyComponent, $('.params')[0])

this actually creates the template, but the blaze component is not initialized, onRendered nor onCreated both won't run...

How could I make this work please?

mitar commented 9 years ago

I think you should try to avoid manipulating Blaze templates directly. Those methods like Blaze.render are used and Blaze.remove are used when inter-operating with 3rd party code.

The easiest thing for you to achieve what you want is to use reactive-field:

class MainComponent extends BlazeComponent
  onCreated: ->
    @paramVisible = new ReactiveField true

  events: ->
    super.concat
      'click .param-remove': @paramRemove

  paramRemove: ->
    @paramVisible false

class ParamComponent extends BlazeComponent
  @register 'ParamComponent'
<template name="MainComponent">
  {{#if paramVisible}}
    {{> ParamComponent}}
  {{/if}}
</template>
mitar commented 9 years ago

I assume for the second thing that you want to have a list of input boxes and then an empty one at the end always available to enter a new value, no? I would do that by having in template render with for of all values in the list, and then having an extra input box. And then on blur on that extra input box you move the new value to the list, and clear the input box.

mitar commented 9 years ago

So again, think more declaratively. This how Meteor is designed. So instead of trying to control rendering like jQuery (add this, remove this), think about what is the state you want to achieve, how that state should be rendered, and what are transitions. So in the second example you have a state where you have few entries and an empty input box. How is that rendered? Then you have a state when user is entering new value. How is that state represented and how it is rendered? And you have a state when user finishes entering new value. The same. And what are transitions between those states (often through event handlers).

Alino commented 9 years ago

yes I exactly wanted to have a list of inputs and last child should add new one on change. I got it working. Thank you