본문 바로가기

Dev.Project/Todolist_project

[TodoMVC] Step 4. To do list Update Item's Status / list 상태 수정하기

Step 4. To do list에서 Item 상태 수정하기

네번째 단계.

이제는 리스트에서 완료, 미완료를 설정할 수 있도록 하자.

점점 설명할 것도 적어지고, 코드량도 적어진다!


1단계 . View.js 파일을 작성한다.

1-1. bind에 itemToggle을 추가한다.

view.js code>

1
2
3
4
5
6
7
8
9
10
11
//event: itemToggle
//handler: controller.toggleComplete
else if(event === 'itemToggle'){
    console.log('View.prototype.bind.itemToggle execute');
    todo.addEventListener('click'function(event){
        var target = event.target;
        if(target.className === 'toggle'){
            handler({id: self._getItemId(target), completed: target.checked}); //=>item
        }
    });
}
cs


list를 삭제할 때와 마찬가지로 bind 메소드를 통해 event를 등록한다.

또 마찬가지로 event가 일어난 곳이 어느 부분인지 판단하기 위한 if 문을 추가하였다.

template.js 파일에 추가된 html 코드에 checkbox의 className이 toggle 이므로

이 checkbox 에서 발생한 이벤트에만 반응하도록 설정한다.

handler에게 전달하는 객체는 id와 completed라는 속성을 갖고 있다.



1-2. _getItemId 메소드를 수정해준다.

view.js code>

1
2
3
4
5
6
7
8
9
10
11
12
View.prototype._getItemId = function(element, tagName){
    var li;
    if(tagName){
        if (element.parentNode.tagName.toLowerCase() === tagName.toLowerCase()){
            li = element.parentNode;
        }
    } else {
        li = element.parentNode.parentNode;
    }
 
    return parseInt(li.dataset.id, 10);//HTML data-*에서 *이 id인 값을 10진수로 parsing함
};
cs


이번에도 _getItemId 메소드를 통해 상태를 변경할 list를 select 한다.

하지만 이번에는 tagName이 전달되지 않는다.

그래서 이에 따른 분기를 나누도록 한다.

그리고 넘어오는 element를 기준으로 li를 찾아 변수로 저장한 다음 dataset을 통해 해당 id 값을 return 하자. 



1-3. render에 elementComplete라는 viewCommand를 추가해준다.

view.js code>

1
2
3
4
5
//parameter 값에는 id, completed 값이 저장되어 있다.
elementComplete : function(){
    console.log('View.prototype.render.elementComplete execute');
    self._elementComplete(parameter.id, parameter.completed);
}
cs


controller로부터 넘겨받은 parameter 값으로 ( 정확히는 storage ) prototype에 저장되어 있는 메소드를 실행한다.

console.log 메소드는 해당 메소드가 실행되었는지 파악하기 위해 추가해두었다.



1-4. prototype에 _elementComplete라는 메소드를 추가해준다
.

view.js code>

1
2
3
4
5
6
7
View.prototype._elementComplete = function(id, completed){
    console.log('View.prototype.render._elementComplete execute');
    var listItem = document.querySelector('[data-id="' + id +'"]');
    if(listItem){
        listItem.className = completed ? 'completed' : '';
    }
};
cs


삭제와 똑같은 매커니즘으로 listItem을 select한다.

그리고는 completed의 값을 기준으로 그 값을 completed로 할 것인지 공백으로 할 것인지 정해진다.

초반에 default로 설정된 값은 false이다. (미완료)

하지만 이벤트가 발생하면서 true로 변경된 값이 parameter로 넘어오게 된다.

그렇기 때문에 completed가 true이므로 해당 className이 completed로 바뀌게 된다.

className이 바뀌면서 base.css 파일에 저장되어 있던 .completed style이 적용될 것이다!




2단계 . controller.js 파일을 작성한다.

2-1. 생성자 함수에 bind를 추가해준다.

controller.js code>

1
2
3
4
5
6
//이 부분이 추가되었다.
//itemToggle 이벤트를 기다리기 위해 view 에 bind 해준다.
this.view.bind('itemToggle'function(item){
    console.log('Controller.prototype 에서 bind 호출 elementComplete execute');
    self.toggleComplete(item.id, item.completed);
});
cs


더이상 설명이 필요없을 것이라 생각한다.

이벤트를 등록하는 과정이라고 생각하면 된다.




2-2. prototype에 toggleComplete 메소드를 추가해준다.

controller.js code>

1
2
3
4
5
6
7
8
9
10
11
12
Controller.prototype.toggleComplete = function(id, completed){
    console.log('Controller.prototyep.toggleComplete execute');
    var self = this;
    //model에게 변동된 사항을 전달한다.
    self.model.update(id, {completed: completed}, function(){
        //model로 부터 변동된 data을 전달받는다.
        self.view.render('elementComplete', {
            id: id,
            completed: completed
        });
    });
};
cs


이번 Step에서도 마찬가지로, model의 update 메소드를 통해 변경될 data의 id 값과 completed를 전달한다.

그리고 변경된 값을 view에 전달하기 위해 callback 구조로 view를 호출하는 함수를 넘겨준다.




3단계 . model.js 파일을 작성한다.

3-1 . prototype에 update 메소드를 추가해준다.

model.js code>

1
2
3
4
5
Model.prototype.update = function(id, data, callback){
    //controller로부터 전달받은 변동사항을 storage에게 전달하여 데이터를 수정한다.
    console.log('Model.prototype.update execute');
    this.storage.save(data, callback, id);
};
cs


controller로부터 넘겨받은 변동사항을 그대로 storage에 보내 save한다.



4단계 . storage.js 파일을 작성한다.

4-1 . 이번 Step에서는 수정사항이 없다.

storage.js code>

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
Storage.prototype.save = function(updateData, callback, id){
    var data = JSON.parse(localStorage[this._dbName]);
    var todos = data.todos;
 
    callback = callback || function(){};
 
    if(id){
        console.log('Storage.prototype.save execute');
        //updateData에 해당하는 값으로 localStorage에 값을 수정한다.
        for(var i = 0; i < todos.length; i++){
            if(todos[i].id === id){
                for(var key in updateData){
                    todos[i][key] = updateData[key];
                }
                break;
            }
        }
        localStorage[this._dbName] = JSON.stringify(data);
        callback.call(this, todos);
    } else {
        updateData.id = new Date().getTime();
 
        todos.push(updateData);
        localStorage[this._dbName] = JSON.stringify(data);
        callback.call(this, [updateData]);
    }
};
cs


이번에는 id 값이 존재한다. 그렇기 때문에 if 문에 해당하는 코드가 작동된다.

updateData를 todos에 저장하는 것이다.

이중 for 문이 추가되어서 다소 복잡해보일 수도 있지만, 우선 id 값으로 update 데이터에 대한 정보를 받고,

update 데이터의 내용을 배열에 추가하는 과정일 뿐이다.




-The End-