Lion789
Lion789

Reputation: 4482

How do you create an inline edit in backbone view?

so I am trying to get the fields in my backbone model being called in the view, editable and validated by the model. How do I go about doing that? I know there is an html way of doing contenteditable="true" but I am looking for a more backbone oriented way or a way to actually make that validate too.

Here is my current code for my main.js file (but I am not trying to .append it I want it to stay in place and also trying to figure out how to get the field to be called specifically depending on which text they clicked on. Ultimately the button should change too (to save changes).

The main.js

App.Models.User = Backbone.Model.extend({
        defaults: {
            firstName: 'first',
            lastName: 'last',
            email: 'Email',
            phone: '222',
            birthday: 'date'
        },

        validate: function (attrs) {
            if (!attrs.firstName) {
                return 'You must enter a real first name.';
            }
            if (!attrs.lastName) {
                return 'You must enter a real last name.';
            }
            if (attrs.email.length < 5) {
                return 'You must enter a real email.';
            }
            if (attrs.phone.length < 10 && attrs.phone === int) {
                return 'You must enter a real phone number, if you did please remove the dash and spaces.';
            }
            if (attrs.city.length < 2) {
                return 'You must enter a real city.';
            }
        }

    });

App.Views.UserUpdate = Backbone.View.extend({
        model: App.Models.User,
        events: {
            'click .edit': 'editUserProfile'
        },

        editUserProfile: function(field) {
            var field = 
            $('#user').append('<input type="text" class="edit" placeholder="' + field+'" /> ' );
        },

        initialize: function() {
            this.model.on('change', function() {
                this.render();
            }, this);
        },

        render: function() {
            this.$el.html(this.model.get('email'));
        }

    });

This is the jade file:

extends layout
block content   
    div.centerContent
        script(type="text/javascript", src="/js/main.js")

        h4 User goes here with equal before it no space
        div(contenteditable="true") 
            form#user
                - var firstName = "John"
                - var lastName = "Smith"        
                label #{firstName} #{lastName}
                - var email = "[email protected]"
                label.edit #{email}
                - var phone = "555-555-5757"
                label #{phone}
                - var pin = "PIN: LIO20001"     
                label #{pin}
                - var birthday = "07/28/1982"   
                label #{birthday}
            button Post
        hr

        div.user User
            p
                button.edit Edit

Upvotes: 3

Views: 3436

Answers (1)

BMH
BMH

Reputation: 4340

I have created a fiddle for this: http://jsfiddle.net/LTGjT/18/

You should assign the contenteditable and id for each editable label:

- var firstName = "John"
- var lastName = "Smith"        
label #{firstName} #{lastName}
- var email = "[email protected]"
label(contenteditable="true", id="email") #{email}
- var phone = "555-555-5757"
label(contenteditable="true", id="phone") #{phone}
- var birthday = "07/28/1982"   
label(contenteditable="true", id="birthday") #{birthday}

The reason is to recognize what label is being edited by getting the event.target, in your old code the event.target will always be the parent div.

Then in backbone listen to the input event for the change of the label then update the model:

App.Models.User = Backbone.Model.extend({
    defaults: {
        firstName: 'first',
        lastName: 'last',
        email: '[email protected]',
        phone: '222',
        birthday: '01/01/2001'
    },

    initialize: function() {
    },

    validate: function (attrs) {
        if (!attrs.firstName) {
            return 'You must enter a real first name.';
        }
        if (!attrs.lastName) {
            return 'You must enter a real last name.';
        }
        if (attrs.email.length < 5) {
            return 'You must enter a real email.';
        }
        if (attrs.phone.length < 10 && attrs.phone === int) {
            return 'You must enter a real phone number, if you did please remove the dash and spaces.';
        }
        if (attrs.city.length < 2) {
            return 'You must enter a real city.';
        }
    }

});

App.Views.UserUpdate = Backbone.View.extend({
    model: App.Models.User,
    events: {
        'click button' : 'saveHandler'
    },

    initialize: function() {
        var self = this;
        self.render();
        console.log(this.model);
        $('[contenteditable=true]').on('input', function(e){
            var field = e.target.id;
            var value = e.target.innerText;
            self.model.set(field, value);
            logUser(self.model);
        });
        self.model.on('change', function(){
            $('button').show();
        });
    },

    saveHandler: function(e) {
        //Validate & Save logic
        //this.model.save()
        e.preventDefault();
        $(e.target).hide();
    },

    render: function() {
        var template = _.template($('#user-view').html());
        this.$el.html(template({user: this.model.toJSON()}));            
        $('body').prepend(this.$el);
        logUser(this.model);
    }

});

Upvotes: 4

Related Questions