Federico Zacayan

Software Devloper.

Vue.js

Create an index.html file and load the cdn to load Vue.js library.

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Vue - Tutorial</title>
</head>
<body>
    <div id="app">
        ...
    </div>
</body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="usercomponent.js"></script>
<script src="index.js"></script>
</html>

Create an index.js file where we make the request to the server.

new Vue({
    el: '#app',
    data: {
        users: []
    },
    mounted() {
        fetch('http://jsonplaceholder.typicode.com/users')
        .then(res => res.json())
        .then((data) => {
            console.log(data);
            this.users = data;
        })
        .catch(console.log)
    }
});

Create an usercomponent.js to render the users.

Vue.component('usercomponent', {
    template: '#user-template'
});

We need to create a template which contains 'user-template' as id. We can write it below of #app container in index.html

<div id="app">
    ...
</div>

<script type="text/x-template" id="user-template">
    <div>
        <span>Name: {{userprop.name}}<br/>
        <span>Email: {{userprop.email}}</span><br/>
        <span>Phone: {{userprop.phone}}</span>
        <hr/>
    </div>
</script>

We can make one or more instances ot this component, but only inside of #app container in index.html

<div id="app">
    <usercomponent v-for="user in users" :userprop="user" v-bind:key="user.id"></usercomponent>
</div>

The variable 'users' have to be into the scope of #app container.

The prop 'userprop' has to be enable in the component in usercomponent.js

Vue.component('usercomponent', {
    template: '#user-template',
    props: ['userprop'],
});

You can test the application now.

To delete an user we can add a buttom into the template.

<input type="button" v-on:click='drop(userprop.id)' value="Delete"/>

We need also to create a method drop into the usercomponent.js

Vue.component('usercomponent', {
    template: '#user-template',
    props: ['userprop'],
    methods: {
        drop(id) {
            this.$emit('delete-user-event', id);
        }
    }
});

With the $emit method we can access to a method of the parent of the current component. See index.html.

<div id="app">
    <usercomponent v-for="user in users" :userprop="user"
    v-bind:key="user.id" @delete-user-event="deleteUser" ></usercomponent>
</div>

Now, we have to add deleteUser method in the #app container.

new Vue({
    el: '#app',
    data: {
        users: []
    },
    mounted() {
        ...
    },
    methods: {
        deleteUser(id) {
            fetch('https://jsonplaceholder.typicode.com/users/' + id, {
                method: 'DELETE'
            })
            .then(() => {
                console.log('deleted');
                let tmp = this.users.filter((a) => {
                    return a.id !== id;
                })
                this.users = tmp;
            })
        }
    }
});

Now you can test the removal functionality.

To update the user we will avoid UX requirements and we will use the attribute contenteditable with true value.

And we implement blur event to trigger the updates.

<script type="text/x-template" id="user-template">
    <div>
        <span>Name:  <span contenteditable="true"
        v-on:blur="update($event, 'name', userprop)">{{userprop.name}}</span></span><br/>
        <span>Email: <span contenteditable="true"
        v-on:blur="update($event, 'email', userprop)">{{userprop.email}}</span></span><br/>
        <span>Phone:  <span contenteditable="true"
        v-on:blur="update($event, 'phone', userprop)">{{userprop.phone}}</span></span>
        <input type="button" v-on:click='drop(userprop.id)' value="Delete"/>
        <hr/>
    </div>
</script>

Now we have to implement the method update in the component.

Vue.component('usercomponent', {
    template: '#user-template',
    props: ['userprop'],
    methods: {
        ...
        update(obj, field, user) {
            console.log(obj.target.innerHTML);
            user[field] = obj.target.innerHTML;
            this.$emit('update-user-event', user);
        }
    }
});

We have to use $emit method to achieve the method of the parent #app

<usercomponent
    v-for="user in users"
    :userprop="user"
    v-bind:key="user.id"
    @delete-user-event="deleleUser"
    @update-user-event="updateUser">
</usercomponent>

Then, we need to make a request in the main component into #app in the method updateUser.

new Vue({
    el: '#app',
    data: {
        users: []
    },
    mounted() {
        ...
    },
    methods: {
        ...
        updateUser(post) {
            console.log("Updating " + post.id);
            fetch('https://jsonplaceholder.typicode.com/users/' + post.id, {
                method: 'PUT',
                body: JSON.stringify(post),
                headers: {
                    "Content-type": "application/json; charset=UTF-8"
                }
            })
            .then(response => response.json())
            .then(json => console.log(json))
        }
    }
});

You can test the update functionality now.

Finaly, we can add a button to create a new user placing it just below the usercomponent, but into #app container.

<input type="button" v-on:click='create()' value="Create new  User"/>

And implement the method to make a request which generate a new user.

new Vue({
    el: '#app',
    data: {
        users: []
    },
    mounted() {
        ...
    },
    methods: {
        ...
        create() {
            console.log('creating user');
            fetch('https://jsonplaceholder.typicode.com/posts', {
                method: 'POST',
                body: JSON.stringify({
                    name: 'Jhon Doe',
                    email: 'bar@email.com',
                    phone: '444-555'
                }),
                headers: {
                    "Content-type": "application/json; charset=UTF-8"
                }
            })
            .then(response => response.json())
            .then(json => {
                console.log(json)
                this.users.push(json);
            })
        }
    }
});

The final source are the following.

index.html.

<!DOCTYPE html>
<html>

<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Vue -Tutorial</title>
</head>

<body>
    <div id="app">
        <usercomponent
            v-for="user in users"
            :userprop="user"
            v-bind:key="user.id"
            @delete-user-event="deleleUser"
            @update-user-event="updateUser">
        </usercomponent>
        <input type="button" v-on:click='create()' value="Create new  User" />
    </div>


    <script type="text/x-template" id="user-template">
        <div>
            <span>Name:  <span contenteditable="true"
            v-on:blur="update($event, 'name', userprop)">{{userprop.name}}</span></span><br/>
            <span>Email: <span contenteditable="true"
            v-on:blur="update($event, 'email', userprop)">{{userprop.email}}</span></span><br/>
            <span>Phone:  <span contenteditable="true"
            v-on:blur="update($event, 'phone', userprop)">{{userprop.phone}}</span></span>
            <input type="button" v-on:click='drop(userprop.id)' value="Delete"/>
            <hr/>
        </div>
    </script>

</body>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="usercomponent.js"></script>
<script src="index.js"></script>

</html>

usercomponent.js.

Vue.component('usercomponent', {
    template: '#user-template',
    props: ['userprop'],
    methods: {
        drop(id) {
            this.$emit('delete-user-event', id);
        },
        update(obj, field, user) {
            console.log(obj.target.innerHTML);
            user[field] = obj.target.innerHTML;
            this.$emit('update-user-event', user);
        }
    }
});

index.js.

new Vue({
    el: '#app',
    data: {
        users: []
    },
    mounted() {
        fetch('http://jsonplaceholder.typicode.com/users')
        .then(res => res.json())
        .then((data) => {
            console.log(data);
            this.users = data;
        })
        .catch(console.log)
    },
    methods: {
        deleleUser(id) {
            fetch('https://jsonplaceholder.typicode.com/users/' + id, {
                method: 'DELETE'
            })
            .then(() => {
                console.log('deleted');
                let tmp = this.users.filter((a) => {
                    return a.id !== id;
                })
                this.users = tmp;
            })
        },
        updateUser(post) {
            console.log("Updating " + post.id);
            fetch('https://jsonplaceholder.typicode.com/users/' + post.id, {
                method: 'PUT',
                body: JSON.stringify(post),
                headers: {
                    "Content-type": "application/json; charset=UTF-8"
                }
            })
            .then(response => response.json())
            .then(json => console.log(json))
        },
        create() {
            console.log('creating user');
            fetch('https://jsonplaceholder.typicode.com/posts', {
                method: 'POST',
                body: JSON.stringify({
                    name: 'Jhon Doe',
                    email: 'bar@email.com',
                    phone: '444-555'
                }),
                headers: {
                    "Content-type": "application/json; charset=UTF-8"
                }
            })
            .then(response => response.json())
            .then(json => {
                console.log(json)
                this.users.push(json);
            })
        }
    }
});