Victor Mendes
Victor Mendes

Reputation: 179

Angular 2 interface and LocalStorage Service

I'm trying to use localstorage as a service to save some datas, so I created an interface and a component to call both (LocalStorage Service and interface).

Interface:

export interface Items {
    id: number;
    title: string;
    message: string;
    done: boolean;
}

Service:

@Injectable()
export class LocalStorageService {

    saved: string = localStorage.getItem('currentItem');
    currentItem: string = (localStorage.getItem('currentItem') !== null) ? JSON.parse(this.saved) : [  ];
    todos: any = this.currentItem;

    save(id, title, message, done) {
        this.todos.push({
            id: id,
            title: title,
            message: message,
            done: false
        });

        localStorage.setItem('currentItem', JSON.stringify(this.todos));
    }

}

Component:

export class AddComponent implements OnInit {

    todoForm: FormGroup;

    currentItem: string;
    todos: any;

    constructor(fb: FormBuilder,
                private router: Router,
                private storageService: LocalStorageService,
                private items: Items) {
        this.currentItem = (localStorage.getItem('currentItem') !== null) ? JSON.parse(localStorage.getItem('currentItem')) : [  ];
        this.todos = this.currentItem;

        this.todoForm = fb.group({
            id: '',
            title: '',
            message: '',
            done: ''
        });
    }

    addTodo(event) {
        console.log(this.todoForm.value);
        this.storageService.save(this.items.id, this.items.title, this.items.message, this.items.done)
        this.router.navigate(['./list']);
    }

   ngOnInit() {}

}

HTML:

<div class="container">
    <form (submit)="addTodo($event)">

        <div class="form-group">
            <label>Id:</label>
            <input [(ngModel)]="id" class="textfield form-control" name="id" />
        </div>

        <div class="form-group">
            <label>Titulo:</label>
            <input [(ngModel)]="title" class="textfield form-control" name="title">
        </div>

        <div class="form-group">
            <label>Mensagem:</label>
            <input [(ngModel)]="message" class="textfield form-control" name="message">
        </div>

        <button type="submit" class="btn btn-success">Salvar</button>
    </form>
</div>

I have a lot of erros when I try to access the html file.

I'm doing a proof of concepts to testing Angular 2 and I would like to use localStorage as a service and an interface. I know that I don't need localStorage as a service to do it works, but in a big project I think I'll need to use it as a service.

The project I'll develop must be works offline, so instead to call localStoragein all components I'm create this localStorage Service.

Does anyone know how I fix this problems?

Using interface and LocalStorage as a service is the best way to develop a big project?

Upvotes: 1

Views: 1545

Answers (1)

AVJT82
AVJT82

Reputation: 73357

You have quite a few errors in your code. I can start first off that skip localStorage altogether. You can just use the service as is, without needing to mix in the local storage there. In a real life app you would make http calls to retrieve data, like something like this:

addTodo(todo) {
  //make api request, handle response, return result to component
}

getTodos() {
  //make api request, handle response, return result to component
}

You can do exactly the same with your app, but have a local array, e.g todos, so your service could look like this:

@Injectable() 
export class LocalStorageService {

  todos: Item[];

  constructor() {
    // lets add one item by default
    this.todos = [{id:1,title:'title1',message:'message1',done:false}]
  }

  getTodos() {
    return this.todos;
  }

  addTodo(todo) {
    this.todos.push(todo)
  }
}

These todos are available for you during your offline session! :)


Then off to your Component, errors you have:

  1. Do not inject items to your constructor, constructor are for providers only
  2. You are mixing template-driven forms with reactive forms
  3. In your addTodo function you are referring to e.g this.items.id, but nowhere in your component there is an item

Okay, let's look at your form, here I changed your form to template driven, so remove FormGroup altogether. You also do not need two way binding. You can construct your form so that the object you get from your form is in the correct format, so that can be pushed to the todos as is. This you achieve in your form by using name attribute together with ngModel, which binds your form. The name attribute will become the key in the object, and of course the value you enter in your form, will become the corresponding value to your key. So your form would look like this:

<form #myForm="ngForm" (ngSubmit)="addTodo(myForm.value)">
  <label>Id:</label>
  <input name="id" ngModel />
  <label>Titulo:</label>
  <input name="title" ngModel />
  <label>Mensagem:</label>
  <input name="message" ngModel />
  <button type="submit">Salvar</button>
</form>

This produces (myForm.value) an object like:

{
  "id": "",
  "title": "",
  "message": ""
}

...when it's empty. Here you also have one more property done in your object, so upon submit, before pushing this new todo in your array, let's add that property key:

addTodo(value) {
  // push the missing value to object
  value.done = false;
  // call method in service to save the new todo
  this.storageService.save(value)
  // update the list of todos
  this.todos = this.storageService.getTodos();
}

Please do read about Angular from the official docs, they have quite good tutorials. Based on the code you have here, please look at Services, which uses local mockdata, just as you want to do. Also look at Forms, difference between template-driven and model-driven forms!

Just as a bonus, here is a Plunker to play with :)

Upvotes: 1

Related Questions