Akademia MetaPack Uniwersytet Zielonogórski Budowa nowoczesnej aplikacji SPA z wykorzystaniem biblioteki Ember.js Daniel Habowski
Budowa aplikacji SPA z wykorzystaniem biblioteki Ember.js Agenda: 1. Standardowa aplikacja 2. Wprowadzenie do SPA 3. Porównanie 4. Wprowadzenie do Ember.js 5. Jak to wykorzystaliśmy w MetaPack 6. Pytania 2/23
Budowa standardowej aplikacji Aplikacja internetowa (wikipedia): program komputerowy, który pracuje na serwerze i komunikuje się poprzez sieć komputerową z hostem użytkownika komputera z wykorzystaniem przeglądarki internetowej 3/23
Wprowadzenie Typowy schemat komunikacji klasycznej aplikacji internetowej 4/23
ASP.Net MVC (Fiddler) DEMO 5/23
Budowa aplikacji SPA z wykorzystaniem biblioteki Ember.js Aplikacja SPA: Aplikacja webowa Składa się z pojedynczej strony web (HTML+JavaScript+CSS) Dane ładowane dynamicznie na żądanie Nie wymaga przeładowania strony Nie przekierowuje użytkownika na inne strony 6/23
Budowa aplikacji SPA z wykorzystaniem biblioteki Ember.js Schemat komunikacji aplikacji SPA 7/23
SPA (Fiddler) DEMO 8/23
Porównanie Klasyczna aplikacja Strona tworzona przy każdym odwołaniu do niej Kod UI nie oddzielony od logiki biznesowej Konieczność zachowania stanu formularzy między stronami Cache serwerów proxy i przeglądarki nieużywane Serwer angażowany dla każdej akcji użytkownika Konieczność użycia wielu języków np. C# i JavaScript Zaawansowane UI wymaga skomplikowanego JavaScript Tylko online SPA Strona ładowana tylko raz Kod UI całkowicie oddzielony od logiki biznesowej Stan aplikacji jest pamiętany, możliwe jest użycie HTML5 storage Całe UI może być przechowywane w cache Serwer angażowany tylko w celu wykonania logiki biznesowej Aplikacja może być stworzona w jednym języku programowania: JavaScript Dobry framework robi bardzo wiele za programistę Możliwość działania offline 9/23
Budowa aplikacji SPA z wykorzystaniem biblioteki Ember.js Dlaczego Ember.js Obiektowość Computed properties Observers Templates Components Architektura MVC Routing 10/23
Budowa aplikacji SPA z wykorzystaniem biblioteki Ember.js Obiektowość Em.Object() extend() init() create() reopen() App.Address = Em.Object.extend({ init: function () { this._super(); this.set('country', 'POL'); }, name: null, city: null var address = App.Address.create({name: "Kowalski" App.Address.reopen({ country: null 11/23
Computed properties DEMO 12/23
Budowa aplikacji SPA z wykorzystaniem biblioteki Ember.js Computed properties Chaining Dynamic updating Getters / setters Person = Ember.Object.extend({ firstname: null, lastname: null, age: null, fullname: function (key, value, previousvalue) { // setter if (arguments.length > 1) { var nameparts = value.split(/\s+/); this.set('firstname', nameparts[0]); this.set('lastname', nameparts[1]); } // getter return this.get('firstname') + ' ' + this.get('lastname'); }.property('firstname', 'lastname'), description: function () { return this.get('fullname')+'; Age: '+this.get('age')+';'; }.property('fullname', 'age') var captainamerica = Person.create({ age: 80 captainamerica.set('fullname', "William Burnside"); captainamerica.get('lastname'); // Burnside captainamerica.get('description'); // "William Burnside; Age: 80; Źródło: http://guides.emberjs.com 13/23
Budowa aplikacji SPA z wykorzystaniem biblioteki Ember.js Observers Person = Ember.Object.extend({ firstname: null, lastname: null, fullname: function() { return this.get('firstname'); + ' ' + this.get('lastname'); }.property('firstname', 'lastname'), fullnamechanged: function() { // deal with the change }.observes('fullname') var person = Person.create(); person.set('firstname', 'Brohuda'); // observer will fire person.addobserver('fullname', function() { // deal with the change Źródło: http://guides.emberjs.com 14/23
Aggregation DEMO 15/23
Budowa aplikacji SPA z wykorzystaniem biblioteki Ember.js Aggregation Monitorowanie listy Insert remove value change Tylko jeden poziom init: function () { this.set('sentconsignments',this.loadallconsignments()); }, totalweight: function () { var sum = 0; this.get('sentconsignments').foreach(function(consignment){ var weight = parsefloat(consignment.get('weight')); sum += weight; return sum; }.property('sentconsignments.@each.weight') Źródło: http://guides.emberjs.com 16/23
Views handlebars DEMO 17/23
Budowa aplikacji SPA z wykorzystaniem biblioteki Ember.js TEMPLATES Expressions Outlets Conditionals Lists Actions helpers <div class="toolbar">{{outlet "toolbar"}}</div> {{#if model}} {{{model.detailsashtml}}} {{else}} <div class="alert" role="alert"> <b>consignment not found</b> </div> {{/if}} {{#link-to 'createconsignment' classnames="btn btn-success"}} Create another consignment {{/link-to}} {{#each consignment in model.consignments}} {{render 'consignmentdetails' consignment}} {{else}} <b>no consignments found...</b> {{/each}} 18/23
Validation component DEMO 19/23
Budowa aplikacji SPA z wykorzystaniem biblioteki Ember.js Components <label>{{label}}</label> {{input class="form-control" type="text" value=value}} <span class="field-validation-valid"></span> App.InputValidatedComponent = Em.Component.extend({ didinsertelement: function () { var elid = (App.customId++).toString(); this.$('input').attr({ 'name': elid, 'data-val': true, 'data-val-required': "Required field" } {{input-validated label="name" value=model.name}} 20/23
Budowa aplikacji SPA z wykorzystaniem biblioteki Ember.js Model View - Controller <b>your consignment with id: {{model.id}} has been successful sent: </b> {{createdate}} App.ConsignmentController = Em.Controller.extend({ createdate: function () { return App.formatDateTime(this.get('model.date')); }.property('model.date') App.Consignment = Em.Object.extend({ date: Date.now() Źródło: http://guides.emberjs.com 21/23
Routing DEMO 22/23
Budowa aplikacji SPA z wykorzystaniem biblioteki Ember.js Routing URL = application state Wildcards Dynamic segments Nested routes Query parameters App.Router.map(function () { this.route('createconsignment', { path: '/consignments/new' this.resource('createdconsignmentdata', {path:'/consignments/:consignmentid' this.route('bad_url', { path: '/*badurl' App.CreatedConsignmentDataRoute = Em.Route.extend({ controllername: 'consignment', model: function (params, transition) { return this.controllerfor('application').getconsignment(params.consignmentid); } App.LoadingRoute = Em.Route.extend({ rendertemplate: function() { this.render("loading"); } Źródło: http://guides.emberjs.com 23/23
Web Shipping Client DEMO 24/23
Akademia MetaPack Uniwersytet Zielonogórski Warsztaty 22-04-2015 Szafrana 2, bud. A2, sala 409 Daniel Habowski