/danilovaz

@_danilovaz

  • Um framework para criar aplicações web ambiciosas
  • Criado pensando na produtividade do desenvolvedor
  • Opinado e alinhado com os Padrões Web
  • Convenção ao invés de configuração
  • Core Team trabalhando em apps reais e robustos

It's more important to reduce the effort of maintenance than it's to reduce the effort of implementation.

Max Kanat-Alexander, Code Quality

  • Manter organizado
  • Modularizar o código
  • Separar as responsabilidades
  • Estabelecer convenções para a equipe
  • Manter tudo testável
//app/models/user.js

import Ember from 'ember';
import DS from 'ember-data';

export default DS.Model.extend({
  firstName: DS.attr('string'),
  lastName: DS.attr('string'),
  fullName: Ember.computed('firstName', 'lastName', function() {
    return `${this.get('firstName')} ${this.get('lastName')}`;
  })
});
  • Renderiza um template
  • Carrega um model e disponibiliza para o template
  • Redireciona para uma nova rota
  • Manipula ações que envolvem mudanças em um model
//app/router.js


Router.map(function() {
  this.route('posts', { path: '/posts' });
});
//app/router.js

Router.map(function() {
  this.route('posts', { path: '/posts' }, function() {
    this.route('new');
  });
});

Rotas

Rotas Aninhadas

//app/router.js

Router.map(function() {
  this.route('posts', { path: '/posts' }, function() {
    this.route('new');
    this.route('post', { path: '/post/:post_id' });
  });
});

//app/routes/post.js

import Ember from 'ember';

export default Ember.Route.extend({
  model(params) {
    return this.get('store').findRecord('post', params.post_id);
  }
});
//app/templates/photos.hbs

<h1>Posts</h1>

{{#each model as |post|}}
  {{#link-to 'post' post.id}}
    {{post.title}}
  {{/link-to}}
{{/each}}
  • Template engine Handlebars
  • Helpers e Built-in Helpers
  • Input Helpers
  • Actions
//app/templates/application.hbs

<p>Olá, <strong>{{firstName}} {{lastName}}</strong>!</p>
<p>Seja bem vindo ao Hackers House!</p>

Handlebars

Helpers

//app/helpers/sum.js

import Ember from 'ember';

export function sum(params) {
  return params.reduce((a, b) => {
    return a + b;
  });
};

export default Ember.Helper.helper(sum);
//app/templates/application.hbs

<p>Total: {{sum 1 2 3}}</p>

Built-in Helpers

{{#if authenticated}}
  <p>Bem vindo, <strong>{{user.firstName}} {{user.lastName}}</strong>!</p>
{{else}}
  <p>Por favor, é necessário fazer o login para acessar essa página.</p>
{{/if}}
<ul>
  {{#each users as |user|}}
    <li>{{user.firstName}}!</li>
  {{/each}}
</ul>
{{input type="text" value=firstName disabled=entryNotAllowed size="50"}}
{{input type="checkbox" name="isAdmin" checked=isAdmin}}
{{textarea value=description cols="80" rows="6"}}

Actions

//app/components/single-post.hbs

<p><button {{action "select" post}}>✓</button> {{post.title}}</p>
//app/components/single-post.js

import Ember from 'ember';

export default Ember.Component.extend({
  actions: {
    select(post) {
      console.log(post.get('title'));
    }
  }
});
  • Template engine Handlebars
  • Helpers e Built-in Helpers
  • Input Helpers
  • Actions
  • Web Components
  • Reutilizáveis
//HTML renderizado

<nav class="nav-bar">
  <ul>
    <li><a href="/" id="ember323" class="active ember-view">Início</a></li>
    <li><a href="/posts" id="ember324" class="ember-view">Posts</a></li>
  </ul>
</nav>
//app/components/navigation-bar.js

import Ember from 'ember';

export default Ember.Component.extend({
  classNames: ['nav-bar'],
  tagName: 'nav'
});
//app/templates/components/navigation-bar.hbs

<ul>
  <li>{{#link-to "home"}}Início{{/link-to}}</li>
  <li>{{#link-to "post"}}Posts{{/link-to}}</li>
</ul>

+

=

//app/templates/application.hbs

{{navigation-bar}}

Só precisamos gerar um Controller se desejarmos customizar suas propriedades ou providenciar alguma action. Caso contrário, se você não gerar um, o Ember irá provindenciar uma instância de um Controller em run time.

//app/templates/blog-post.hbs

<h1>{{model.title}}</h1>
<h2>Autor: {{model.author}}</h2>

<div class='intro'>
  {{model.intro}}
</div>

<hr>

{{#if isExpanded}}
  <button {{action "toggleBody"}}>Ver menos</button>
  <div class="body">
    {{model.body}}
  </div>
{{else}}
  <button {{action "toggleBody"}}>Ver mais</button>
{{/if}}
//app/controllers/blog-post.js

import Ember from 'ember';

export default Ember.Controller.extend({
  actions: {
    toggleBody() {
      this.toggleProperty('isExpanded');
    }
  }
});
  • Arquitetura
  • Definição
  • Relacionamento
  • CRUD
  • Caching
//app/models/post.js

import DS from 'ember-data';

export default DS.Model.extend({
  title: DS.attr('string'),
  body: DS.attr('string'),
  published: DS.attr('boolean', { defaultValue: false }),
  createdAt: DS.attr('date', {
    defaultValue() { return new Date(); }
  })
});
//app/models/user.js

import DS from 'ember-data';

export default DS.Model.extend({
  name: DS.attr('string'),
  profile: DS.belongsTo('profile')
});
//app/models/profile.js

import DS from 'ember-data';

export default DS.Model.extend({
  title: DS.attr('string'),
  user: DS.belongsTo('user')
});

One-to-One

//app/models/post.js

import DS from 'ember-data';

export default DS.Model.extend({
  title: DS.attr('string'),
  body: DS.attr('string'),
  published: DS.attr('boolean', { defaultValue: false }),
  createdAt: DS.attr('date', {
    defaultValue() { return new Date(); }
  })
  comments: DS.hasMany('comment')
});
//app/models/comment.js

import DS from 'ember-data';

export default DS.Model.extend({
  text: DS.attr('string'),
  post: DS.belongsTo('post')
});

One-to-Many

//app/models/post.js

import DS from 'ember-data';

export default DS.Model.extend({
  title: DS.attr('string'),
  body: DS.attr('string'),
  published: DS.attr('boolean', { defaultValue: false }),
  createdAt: DS.attr('date', {
    defaultValue() { return new Date(); }
  })
  comments: DS.hasMany('comment'),
  tags: DS.hasMany('tag')
});
//app/models/tag.js

import DS from 'ember-data';

export default DS.Model.extend({
  title: DS.attr('string'),
  post: DS.hasMany('post')
});

Many-to-Many

let post = store.createRecord('post', {
  title: 'Ember.js no Hackers House',
  body: 'Lorem ipsum'
});

// => chamada POST em '/posts'
post.save();
// => chamada GET em /posts
let posts = this.get('store').findAll('post');

// => chamada GET em /posts/1
let post = this.get('store').findRecord('post', 1);

Create

Read

this.get('store').findRecord('user', 1).then(function(response) {
  // após o dado ter sido carregado
  response.set('firstName', "Danilo Vaz");
});
// => chamada DELETE em /posts/2
store.findRecord('post', 2, { backgroundReload: false }).then(function(post) {
  post.destroyRecord();
});

Update

Delete

// => Nenhuma requisição web é feita. Busca no Storage.

let posts = this.get('store').peekAll('post');

peekAll

peekRecord

// => Nenhuma requisição web é feita. Busca no Storage.

let post = this.get('store').peekRecord('post', 1);
  • DS.Adapter
  • DS.JSONAPIAdapter
  • DS.RESTAdapter
//app/adapters/application.js

import DS from 'ember-data';

export default DS.JSONAPIAdapter.extend({
  session: Ember.inject.service('session'),
  host: 'https://api.meusite.com.br',

  headers: Ember.computed('session.authToken', function() {
    return {
      'TOKEN': this.get('session.authToken'),
      'OUTRO-HEADER': 'Hackers House 2017'
    };
  })
});
{
  "data": {
    "id": "1",
    "type": "product",
    "attributes": {
      "name": "My Product",
      "amount": 100,
      "currency": "SEK"
    }
  }
}
{
  "data": {
    "id": "1",
    "type": "product",
    "attributes": {
      "name": "My Product",
      "cost": {
        "amount": 100,
        "currency": "SEK"
      }
    }
  }
}
import DS from 'ember-data';

export default DS.JSONAPISerializer.extend({
  serialize(snapshot, options) {
    let json = this._super(...arguments);

    json.data.attributes.cost = {
      amount: json.data.attributes.amount,
      currency: json.data.attributes.currency
    };

    delete json.data.attributes.amount;
    delete json.data.attributes.currency;

    return json;
  },
});
  • Glimmer 2
  • Fastboot
  • RFCS

Ember - Por que você ainda não está usando

By Danilo Vaz

Ember - Por que você ainda não está usando

Por que você ainda não está usando Ember?

  • 1,025