Oner Ksor
Oner Ksor

Reputation: 931

creating element on click in Meteor

I'm using Meteor with React. I have a really simple goal, but i have tried a lot and can't solve it for myself. I will show you my attemps below.

I want to create a form for the Ingredients. At the first moment there is only one input (for only one ingredient) and 2 buttons: Add Ingredient and Submit.

class IngredientForm extends Component {
  render() {
    return(

      <form onSubmit={this.handleSubmit.bind(this)}>

        <input type="text"/>

        { this.renderOtherInputs() }

        <input type="button" value="Add Ingredient" onClick={this.addIngredient.bind(this)}>

        <input type="submit" value="Submit Form">

      </form>
    );
  }
}

So when I click Submit then all the data goes to the collection. When I click Add Ingredient then the another text input appears (in the place where renderOtherInputs() ).

I know, that Meteor is reactive - so no need to render something directly. I should underlie on the reactive data storage.

And I know from the tutorials the only one way to render something - I should have an array (that was based on collection, which is always reactive) and then render something for each element of that array.

So I should have an array with number of elements = number of additional inputs. that is local, so I can't use Collection, let's use Reactive Var instead of it.

numOfIngredients = new ReactiveVar([]);

And when I click Add button - the new element should be pushed to this array:

addIngredient(e) {
    e.preventDefault();
    let newNumOfIngredients = numOfIngredients.get();
    newNumOfIngredients.push('lalal');
    numOfIngredients.set(newNumOfIngredients);
}

And after all I should render additional inputs (on the assumption of how many elements I have in the array):

renderOtherInputs() {
  return numOfIngredients.get().map((elem) => {
    return(
      <input type="text"/>
    );
  }
}

The idea is: when I click Add button then new element is pushed to the ReactiveVar (newNumOfIngredients). In the html code I call this.renderOtherInputs(), which return html for the as many inputs as elements I have in my ReactiveVar (newNumOfIngredients). newNumOfIngredients is a reactive storage of data - so when I push element to it, all things that depends on it should re-render. I have no idea why that is not working and how to do this.

Thank you for your help.

Upvotes: 0

Views: 176

Answers (1)

Oner Ksor
Oner Ksor

Reputation: 931

Finally I got the solution. But why you guys don't help newbie in web? It is really simple question for experienced developers. I read that meteor and especially react have powerful communities, but...

the answer is: we should use state!

first let's define our state object in the constructor of react component:

constructor(props) {
  super(props);
  this.state = {
    inputs: [],
  }
}

then we need a function to render inputs underlying our state.inputs:

renderOtherInputs() {
  return this.state.inputs.map( (each, index) => {
    return (
      <input key={ index } type="text" />
    );
  });
} 

and to add an input:

addInput(e) {
  e.preventDefault();
  var temp = this.state.inputs;
  temp.push('no matter');
  this.setState({
    inputs: temp,
  });
}

p.s. and to delete each input:

deleteIngredient(e) {
  e.preventDefault();
  let index = e.target.getAttribute('id');
  let temp = this.state.inputs;
  delete temp[index];
  this.setState({
    inputs: temp,
  });
}

Upvotes: 0

Related Questions