Read/Edit mode in form by double click on element in article


#1

I’m working on arabic-russian dictionary, and using Blaze (honestly I avoid React because I like using bootstrap in ordinary way with pure html, may be I’m wrong).

In each word article there are too many fields, like word-forms, translations, examples, example’s translation etc. I want to open micro edit forms for all item of the particular data.

{note, word} 
    {translation} 
        {example, translation} 

That’s how looks word-article:

Screenshot from 2017-10-06 19-10-22

For each data item there is hidden inputs, for change them. Micro edit forms are pairs of input in most of cases. Or one input for translation. I want to hide displayed data by dblclick on it, and open micro-form for change it. But I can’t understand clearly how it realize without make code unreadable and ugly.

That is how looks pair display/edit for word item:

<div class="wordDisplay display">
    <div id="article.{{../_id}}.words.{{@index}}.note" class="note">{{note}}</div>
    <div id="article.{{../_id}}.words.{{@index}}.word" class="word -arabic-text-big">{{word}}</div>
</div>

<div class="wordEdit editField" id="article.{{../_id}}.words.{{@index}}">
    <input type="text" placeholder="примечание" value="{{note}}" name="article.{{../_id}}.words.{{@index}}.note" class="form-control note">
    <input type="text" placeholder="слово" value="{{word}}" name="article.{{../_id}}.words.{{@index}}.word" class="form-control word -arabic-text-big">
</div>

That is how I handle changing:

Template.ArticleSingle.events({ 
    'change input'(event){
        let doc = eventToDoc(event.target.name, event.target.value)
        Meteor.call('articles.update', doc)
        //console.log(event.target.name, event.target.value)
    },

Changing works fine. Now question is, how to realize Open/Hide functionality…
I have one idea to make helpers with to long id’s of elements. But then code will be so ugly…
Please, share your ideas.


#2

I have found an answer. I just created 3 additional helpers, where I calculate wordId, translationId etc, and use them in instead of “article.{{…/_id}}.words.{{@index}}” in template.
There are helpers:

    isEditModeForId(id){
        const instance = Template.instance()
        return id == instance.editModeFor.get()
    },
    words(){
        let newWords = this.words.map((elem, index) => {
            return {note: elem.note, word: elem.word, wordId: `article.${this._id}.words.${index}`}
        })
        return newWords
    },
    translations(){
        //article.{{../_id}}.translations.{{@index}}.translation
        let newTranslations = this.translations.map((elem, index) => {
            return {
                    translation: elem.translation, 
                    translationId: `article.${this._id}.translations.${index}.translation`, 
                    examples: elem.examples.map((elem2, index2)=>{
                        return {
                                example: elem2.example,
                                translation: elem2.translation,
                                exampleId: `article.${this._id}.translations.${index}.examples.${index2}`
                            }
                    })
                }
        })
        return newTranslations
    },

And there is template:

{{#unless isEditModeForId wordId}}
    <div class="wordDisplay display">
        <div id="{{wordId}}.note" class="note">{{note}}</div>
        <div id="{{wordId}}.word" class="word -arabic-text-big">{{word}}</div>
    </div>
{{/unless}}
{{#if isEditModeForId wordId}}
    <div class="wordEdit editField" id="{{wordId}}">
        <input type="text" placeholder="примечание" value="{{note}}" name="{{wordId}}.note" class="form-control note">
        <input type="text" placeholder="слово" value="{{word}}" name="{{wordId}}.word" class="form-control word -arabic-text-big">
    </div>
{{/if}}

#3

Just a heads up – you can also use else in your templates:

{{#if isEditModeForId wordId}}
 <!-- your wordEdit code -->
{{else}}
  <!-- your wordDisplay code -->
{{/if}}