Oikean työkalun valinta oikeaan tarkoitukseen menee pitkälle, varsinkin kun on kyse nykyaikaisten verkkosovellusten rakentamisesta. Monet meistä tuntevat AngularJS: n ja kuinka helppoa se tekee vankan verkkosovelluksen käyttöliittymien kehittämisen. Vaikka monet vastustavat tämän suositun verkkokehyksen käyttöä, sillä on varmasti paljon tarjottavaa ja voi olla sopiva valinta monenlaisiin tarpeisiin. Toisaalta taustalla käyttämäsi komponentit sanelevat paljon verkkosovelluksen suorituskyvystä, koska ne vaikuttavat yleiseen käyttökokemukseen. pelata on nopea ja nopea web-kehys Javaille ja Scalalle. Se perustuu kevyeen, kansalaisuudettomaan, web-ystävälliseen arkkitehtuuriin ja seuraa MVC-malleja ja periaatteita, jotka ovat samanlaisia kuin Rails ja Django.
Tässä artikkelissa tarkastelemme, kuinka voimme käyttää AngularJS ja Play -sovellusta yksinkertaisen blogisovelluksen luomiseen perustodentamismekanismilla ja kyvyllä tehdä viestejä ja kommentteja. KulmaJS-kehitys , jonkun kanssa Twitter Bootstrap herkkuja, voimme antaa yhden sivun sovelluskokemuksen Play-pohjaisen REST-sovellusliittymän taustan päälle.
AngularJS- ja Play-sovellukset sijaitsevat vastaavasti asiakas- ja palvelinhakemistoissa. Toistaiseksi luomme 'asiakas' -hakemiston.
mkdir -p blogapp/client
AngularJS-sovelluksen luuranko luodaan käyttämällä Yeomania - hämmästyttävää rakennustelineitä. Yeomanin asentaminen on helppoa . Sen käyttäminen yksinkertaisen luurankoisen AngularJS-sovelluksen telineeksi on todennäköisesti vielä helpompaa:
cd blogapp/client yo angular
Toisen komennon suorittamista seuraa muutama vaihtoehto, joista sinun on valittava. Tätä projektia varten emme tarvitse “Sassia (kompassilla)”. Tarvitsemme Boostrapin sekä seuraavat AngularJS-laajennukset:
Tässä vaiheessa, kun olet viimeistellyt valintasi, alat nähdä NPM- ja Bower-lähtöjä päätelaitteessasi. Kun lataukset ovat valmiit ja paketit on asennettu, sinulla on AngularJS-sovelluksen luuranko käyttövalmis.
Virallinen tapa luoda uusi Play-sovellus edellyttää Typesafe Activator -työkalun käyttöä. Ennen kuin voit käyttää sitä, sinun on ladattava ja asennettava se tietokoneellesi. Jos käytät Mac OS -käyttöjärjestelmää ja käytät Homebrew-sovellusta, voit asentaa tämän työkalun yhdellä komentorivillä:
brew install typesafe-activator
Play-sovelluksen luominen komentoriviltä on erittäin helppoa:
cd blogapp/ activator new server play-java cd server/
Jos haluat tuoda sovelluksen IDE: hen, kuten Eclipse tai IntelliJ, sinun on 'pimennys' tai 'idealisoitava' sovelluksesi. Suorita se suorittamalla seuraava komento:
activator
Kun näet uuden kehotteen, kirjoita joko 'eclipse' tai 'idea' ja paina Enter valmistellaksesi sovelluskoodia Eclipse- tai IntelliJ-ohjelmille.
Lyhyesti sanottuna tässä artikkelissa käsitellään vain projektin tuontia IntelliJ: ään. Sen tuonti Eclipseen pitäisi olla yhtä yksinkertainen. Jos haluat tuoda projektin IntelliJ: iin, aloita aktivoimalla 'Tiedosto -> Uusi' -vaihtoehto 'Projekti olemassa olevista lähteistä ...'. Valitse seuraavaksi build.sbt-tiedostosi ja napsauta 'OK'. Kun napsautat uudelleen “OK” seuraavassa valintaikkunassa, IntelliJ: n pitäisi alkaa tuoda Play-sovellustasi SBT-projektina.
Typesafe Activatorissa on myös graafinen käyttöliittymä, jota voit käyttää luo tämä luurankosovelluskoodi .
Nyt kun olemme tuoneet Play-sovelluksemme IntelliJ: ään, meidän pitäisi myös tuoda AngularJS-sovelluksemme työtilaan. Voimme tuoda sen joko erillisenä projektina tai moduulina olemassa olevaan projektiin, jossa Play-sovellus sijaitsee.
Täällä tuomme Angular-sovelluksen moduulina. 'Tiedosto' -valikosta valitsemme vaihtoehdon 'Uusi -> Moduuli olemassa olevista lähteistä ...'. Valitsemme valintaikkunasta 'asiakas' -hakemiston ja napsautamme 'OK'. Napsauta seuraavissa kahdessa näytössä Seuraava ja Valmis.
Tässä vaiheessa pitäisi olla mahdollista käynnistää AngularJS-sovellus Grunt-tehtävänä IDE: ltä. Laajenna asiakaskansiota ja napsauta hiiren kakkospainikkeella Gruntfile.js. Valitse ponnahdusvalikosta 'Näytä Grunt Tasks'. Näkyviin tulee paneeli nimeltä Grunt, jossa on luettelo tehtävistä:
Aloita sovelluksen palveleminen kaksoisnapsauttamalla 'serve'. Tämän pitäisi avata oletusselaimesi välittömästi ja osoittaa se paikallisen isännän osoitteeseen. Sinun pitäisi nähdä tynkä AngularJS-sivu, jossa on Yeomanin logo.
Seuraavaksi meidän on käynnistettävä taustapalvelinsovellus. Ennen kuin voimme edetä, meidän on käsiteltävä pari asiaa:
Molempien ongelmien kiertämiseksi meidän on vain käytettävä Grunt-välityspalvelinta, jotta kaikki Play-sovelluksen AJAX-pyynnöt ovat välityspalvelimia. Tämän ansiosta molemmat sovelluspalvelimet ovat olennaisesti käytettävissä samalla näennäisellä porttinumerolla.
Vaihdetaan ensin Play-sovelluspalvelimen porttinumero 9090. Voit tehdä tämän avaamalla Suorita / virheenkorjaus-ikkunan napsauttamalla Suorita -> Muokkaa määrityksiä. Muuta seuraavaksi portin numero kenttään 'Url To Open'. Napsauta “OK” hyväksyäksesi muutoksen ja sulkemalla ikkuna. Napsauttamalla Suorita-painiketta, aloita riippuvuuden selvitysprosessi - tämän prosessin lokit alkavat näkyä.
Kun se on valmis, voit siirtyä selaimellasi osoitteeseen http: // localhost: 9090, ja muutamassa sekunnissa sinun pitäisi pystyä näkemään Play-sovelluksesi. Grunt-välityspalvelimen määrittämiseksi meidän on ensin asennettava pieni Node.js-paketti NPM: n avulla:
cd blogapp/client npm install grunt-connect-proxy --save-dev
Seuraavaksi meidän täytyy säätää Gruntfile.js-tiedostoa. Etsi tiedostosta 'connect' -tehtävä ja lisää sen jälkeen 'proxies' -avain / -arvo:
proxies: [ { context: '/app', // the context of the data service host: 'localhost', // wherever the data service is running port: 9090, // the port that the data service is running on changeOrigin: true } ],
Grunt välittää nyt kaikki “/ app / *” -pyynnöt Play-taustasovellukseen. Tämä säästää meitä siitä, että meidän on lisättävä kaikki back-end-puhelut sallittujen luetteloon. Lisäksi meidän on myös muutettava maksakuormituskäyttäytymistämme:
livereload: { options: { open: true, middleware: function (connect) { var middlewares = []; // Setup the proxy middlewares.push(require('grunt-connect-proxy/lib/utils').proxyRequest); // Serve static files middlewares.push(connect.static('.tmp')); middlewares.push(connect().use( '/bower_components', connect.static('./bower_components') )); middlewares.push(connect().use( '/app/styles', connect.static('./app/styles') )); middlewares.push(connect.static(appConfig.app)); return middlewares; } } },
Lopuksi meidän on lisättävä uusi riippuvuus “’ configureProxies: server ”palvelemaan-tehtävään:
grunt.registerTask('serve', 'Compile then start a connect web server', function (target) { if (target === 'dist') { return grunt.task.run(['build', 'connect:dist:keepalive']); } grunt.task.run([ 'clean:server', 'wiredep', 'concurrent:server', 'autoprefixer:server', 'configureProxies:server', 'connect:livereload', 'watch' ]); });
Kun käynnistät Gruntin uudelleen, sinun tulisi huomata lokissasi seuraavat rivit, jotka osoittavat välityspalvelimen olevan käynnissä:
Running 'autoprefixer:server' (autoprefixer) task File .tmp/styles/main.css created. Running 'configureProxies:server' (configureProxies) task Running 'connect:livereload' (connect) task Started connect web server on http://localhost:9000
Aloitamme luomalla kirjautumislomakkeen blogisovelluksellemme. Tämän avulla voimme myös varmistaa, että kaikki toimii oikein. Voimme käyttää Yeomania luomaan kirjautumisohjaimen ja katselun AngularJS: ssä:
yo angular:controller signup yo angular:view signup
Seuraavaksi meidän on päivitettävä sovelluksemme reititys viittaamaan tähän äskettäin luotuun näkymään ja poistettava turha automaattisesti luotu 'about' -ohjain ja -näkymä. Poista tiedostosta 'app / scripts / app.js' viittaukset 'app / scripts / controllers / about.js' ja 'app / views / about.html' jättäen sen:
.config(function ($routeProvider) { $routeProvider .when('/', { templateUrl: 'views/main.html', controller: 'MainCtrl' }) .when('/signup', { templateUrl: 'views/signup.html', controller: 'SignupCtrl' }) .otherwise({ redirectTo: '/' });
Päivitä vastaavasti app / index.html-tiedosto poistaaksesi turhat linkit ja lisää linkki rekisteröintisivulle:
Poista myös tiedostotunniste about.js:
Email Password Sign up!
Lisää seuraavaksi lomake signup.html-tiedostoon:
angular.module('clientApp') .controller('SignupCtrl', function ($scope, $http, $log) { $scope.signup = function() { var payload = { email : $scope.email, password : $scope.password }; $http.post('app/signup', payload) .success(function(data) { $log.debug(data); }); }; });
Meidän on saatava muoto käsiteltäväksi kulmaohjaimella. On syytä huomata, että meidän ei tarvitse lisätä nimenomaisesti ”ng-controller” -attribuuttia näkymiimme, koska ”app.js” -reitityslogiikkamme käynnistää ohjaimen automaattisesti ennen kuin näkymäämme ladataan. Ainoa, mitä meidän on tehtävä tämän lomakkeen yhdistämiseksi, on oikea laajennusfunktio, joka on määritelty $ -alueella. Tämä tulisi tehdä ”signup.js” -tiedostossa:
public static Result signup() { return ok('Success!'); }
Anna nyt avata Chromen kehittäjäkonsoli, siirtyä Verkko-välilehdelle ja yrittää lähettää rekisteröintilomake.
Näemme, että Play-käyttöliittymä vastaa luonnollisesti Toimintoa ei löydy -virhesivulla. Tämän odotetaan, koska sitä ei ole vielä pantu täytäntöön. Mutta se tarkoittaa myös sitä, että Grunt-välityspalvelinasetuksemme toimii oikein!
Seuraavaksi aiomme lisätä toiminnon, joka on olennaisesti menetelmä Play-sovelluksen ohjaimessa. Lisää luokkaan 'Sovellus' 'sovellus / ohjaimet' -pakettiin uusi menetelmä 'rekisteröityminen':
POST /app/signup controllers.Application.signup
Avaa nyt tiedosto 'conf / route' ja lisää seuraava rivi:
db.default.driver=org.h2.Driver db.default.url='jdbc:h2:mem:play' db.default.user=sa db.default.password='' ... ebean.default='models.*'
Lopuksi palataan verkkoselaimeemme, http: // localhost: 9000 / # / signup. Tällä kertaa napsauttamalla Lähetä-painiketta, pitäisi saada jotain erilaista:
Sinun pitäisi nähdä palautettu kovakoodattu arvo, se, jonka kirjoitimme rekisteröintimenetelmään. Jos näin on, olemme valmiita siirtymään eteenpäin, kun kehitysympäristö on valmis ja toimii sekä Angular- että Play-sovelluksissa.
Ennen kuin määritämme mallit, valitaan ensin tietopiste. Tässä artikkelissa käytämme H2-muistitietokantaa. Ota tämä käyttöön etsimällä ja poistamalla seuraavat rivit tiedostosta ”application.conf”:
applyEvolutions.default=true
Lisää seuraava rivi:
// User.java @Entity public class User extends Model { @Id public Long id; @Column(length = 255, unique = true, nullable = false) @Constraints.MaxLength(255) @Constraints.Required @Constraints.Email public String email; @Column(length = 64, nullable = false) private byte[] shaPassword; @OneToMany(cascade = CascadeType.ALL) @JsonIgnore public List posts; public void setPassword(String password) { this.shaPassword = getSha512(password); } public void setEmail(String email) { this.email = email.toLowerCase(); } public static final Finder find = new Finder( Long.class, User.class); public static User findByEmailAndPassword(String email, String password) { return find .where() .eq('email', email.toLowerCase()) .eq('shaPassword', getSha512(password)) .findUnique(); } public static User findByEmail(String email) { return find .where() .eq('email', email.toLowerCase()) .findUnique(); } public static byte[] getSha512(String value) { try { return MessageDigest.getInstance('SHA-512').digest(value.getBytes('UTF-8')); } catch (NoSuchAlgorithmException e) { throw new RuntimeException(e); } catch (UnsupportedEncodingException e) { throw new RuntimeException(e); } } }
Blogin verkkotunnusmalli on melko yksinkertainen. Ensinnäkin meillä on käyttäjiä, jotka voivat luoda viestejä, ja sitten kuka tahansa kirjautunut käyttäjä voi kommentoida jokaista viestiä. Luodaan Ebean-mallit.
// BlogPost.java @Entity public class BlogPost extends Model { @Id public Long id; @Column(length = 255, nullable = false) @Constraints.MaxLength(255) @Constraints.Required public String subject; @Column(columnDefinition = 'TEXT') @Constraints.Required public String content; @ManyToOne public User user; public Long commentCount; @OneToMany(cascade = CascadeType.ALL) public List comments; public static final Finder find = new Finder( Long.class, BlogPost.class); public static List findBlogPostsByUser(final User user) { return find .where() .eq('user', user) .findList(); } public static BlogPost findBlogPostById(final Long id) { return find .where() .eq('id', id) .findUnique(); } }
// PostComment.java @Entity public class PostComment extends Model { @Id public Long id; @ManyToOne @JsonIgnore public BlogPost blogPost; @ManyToOne public User user; @Column(columnDefinition = 'TEXT') public String content; public static final Finder find = new Finder( Long.class, PostComment.class); public static List findAllCommentsByPost(final BlogPost blogPost) { return find .where() .eq('post', blogPost) .findList(); } public static List findAllCommentsByUser(final User user) { return find .where() .eq('user', user) .findList(); } }
// Application.java public static Result signup() { Form signUpForm = Form.form(SignUp.class).bindFromRequest(); if ( signUpForm.hasErrors()) { return badRequest(signUpForm.errorsAsJson()); } SignUp newUser = signUpForm.get(); User existingUser = User.findByEmail(newUser.email); if(existingUser != null) { return badRequest(buildJsonResponse('error', 'User exists')); } else { User user = new User(); user.setEmail(newUser.email); user.setPassword(newUser.password); user.save(); session().clear(); session('username', newUser.email); return ok(buildJsonResponse('success', 'User created successfully')); } } public static class UserForm { @Constraints.Required @Constraints.Email public String email; } public static class SignUp extends UserForm { @Constraints.Required @Constraints.MinLength(6) public String password; } private static ObjectNode buildJsonResponse(String type, String message) { ObjectNode wrapper = Json.newObject(); ObjectNode msg = Json.newObject(); msg.put('message', message); wrapper.put(type, msg); return wrapper; }
Luodaan nyt ensimmäinen todellinen toimintamme, jonka avulla käyttäjät voivat rekisteröityä:
yo angular:service alerts
Huomaa, että tässä sovelluksessa käytetty todennus on hyvin yksinkertainen, eikä sitä suositella tuotantokäyttöön.
Mielenkiintoinen osa on, että käytämme Play-lomakkeita rekisteröintilomakkeiden käsittelemiseen. Asetimme pari rajoitusta SignUp-lomakeluokkaamme. Vahvistus tehdään meille automaattisesti ilman erillistä vahvistuslogiikkaa.
Jos palaamme AngularJS-sovellukseemme verkkoselaimessa ja napsautamme uudelleen Lähetä, näemme, että palvelin vastaa nyt asianmukaisella virheellä - että nämä kentät ovat pakollisia.
Joten saamme virheitä palvelimelta, mutta sovelluksen käyttäjällä ei ole aavistustakaan mitä tapahtuu. Pienin mitä voimme tehdä, on näyttää virhe käyttäjälle. Ihannetapauksessa meidän on ymmärrettävä, millaista virhettä saamme, ja näytettävä käyttäjäystävällinen viesti. Luodaan yksinkertainen hälytyspalvelu, joka auttaa meitä näyttämään virheen.
Ensin meidän on luotava palvelumalli Yeomanin kanssa:
angular.module('clientApp') .factory('alertService', function($timeout) { var ALERT_TIMEOUT = 5000; function add(type, msg, timeout) { if (timeout) { $timeout(function(){ closeAlert(this); }, timeout); } else { $timeout(function(){ closeAlert(this); }, ALERT_TIMEOUT); } return alerts.push({ type: type, msg: msg, close: function() { return closeAlert(this); } }); } function closeAlert(alert) { return closeAlertIdx(alerts.indexOf(alert)); } function closeAlertIdx(index) { return alerts.splice(index, 1); } function clear(){ alerts = []; } function get() { return alerts; } var service = { add: add, closeAlert: closeAlert, closeAlertIdx: closeAlertIdx, clear: clear, get: get }, alerts = []; return service; } );
Lisää seuraavaksi tämä koodi alerts.js-tiedostoon:
yo angular:controller alerts
Luodaan nyt erillinen ohjain, joka vastaa hälytyksistä:
angular.module('clientApp') .controller('AlertsCtrl', function ($scope, alertService) { $scope.alerts = alertService.get(); });
bower install angular-bootstrap --save
Nyt meidän on todella näytettävä mukavia Bootstrap-virheilmoituksia. Helpoin tapa on käyttää Kulma käyttöliittymä . Voimme käyttää Boweria sen asentamiseen:
angular .module('clientApp', [ 'ngAnimate', 'ngCookies', 'ngResource', 'ngRoute', 'ngSanitize', 'ngTouch', 'ui.bootstrap' ])
Liitä “app.js” -sovellukseen Angular UI -moduuli:
{{ alert.msg }}
Lisätään varoitusdirektiivi index.html-tiedostoon:
angular.module('clientApp') .controller('SignupCtrl', function ($scope, $http, $log, alertService, $location, userService) { $scope.signup = function() { var payload = { email : $scope.email, password : $scope.password }; $http.post('app/signup', payload) .error(function(data, status) { if(status === 400) { angular.forEach(data, function(value, key) { if(key === 'email' || key === 'password') { alertService.add('danger', key + ' : ' + value); } else { alertService.add('danger', value.message); } }); } if(status === 500) { alertService.add('danger', 'Internal server error!'); } }) }; });
Lopuksi meidän on päivitettävä SignUp-ohjain:
yo angular:view dashboard yo angular:controller dashboard
Jos lähetämme tyhjä lomake uudelleen, lomakkeen yläpuolella näkyy virheitä:
Nyt kun virheitä on käsitelty, meidän on tehtävä jotain, kun käyttäjien rekisteröityminen onnistuu. Voimme ohjata käyttäjän hallintapaneelisivulle, johon hän voi lisätä viestejä. Mutta ensin meidän on luotava se:
angular.module('clientApp') .controller('SignupCtrl', function ($scope, $http, $log, alertService, $location) { // .. .success(function(data) { if(data.hasOwnProperty('success')) { $location.path('/dashboard'); } });
Muokkaa “signup.js” -ohjaimen rekisteröintimenetelmää siten, että se ohjaa käyttäjän onnistumisen jälkeen:
.when('/dashboard', { templateUrl: 'views/dashboard.html', controller: 'DashboardCtrl' })
Lisää uusi reitti sovelluksiin.js:
yo angular:service user
Meidän on myös seurattava, onko käyttäjä kirjautunut sisään. Luodaan sille erillinen palvelu:
// user.js angular.module('clientApp') .factory('userService', function() { var username = ''; return { username : username }; });
.success(function(data) { if(data.hasOwnProperty('success')) { userService.username = $scope.email; $location.path('/dashboard');; } });
Ja muokkaa myös rekisteröintiohjainta asettamaan käyttäjä juuri rekisteröivälle:
public static Result login() { Form loginForm = Form.form(Login.class).bindFromRequest(); if (loginForm.hasErrors()) { return badRequest(loginForm.errorsAsJson()); } Login loggingInUser = loginForm.get(); User user = User.findByEmailAndPassword(loggingInUser.email, loggingInUser.password); if(user == null) { return badRequest(buildJsonResponse('error', 'Incorrect email or password')); } else { session().clear(); session('username', loggingInUser.email); ObjectNode wrapper = Json.newObject(); ObjectNode msg = Json.newObject(); msg.put('message', 'Logged in successfully'); msg.put('user', loggingInUser.email); wrapper.put('success', msg); return ok(wrapper); } } public static Result logout() { session().clear(); return ok(buildJsonResponse('success', 'Logged out successfully')); } public static Result isAuthenticated() { if(session().get('username') == null) { return unauthorized(); } else { ObjectNode wrapper = Json.newObject(); ObjectNode msg = Json.newObject(); msg.put('message', 'User is logged in already'); msg.put('user', session().get('username')); wrapper.put('success', msg); return ok(wrapper); } } public static class Login extends UserForm { @Constraints.Required public String password; }
Ennen kuin lisäämme viestien lisäämisen päätoiminnot, huolehditaan joistakin muista tärkeistä ominaisuuksista, kuten mahdollisuudesta kirjautua sisään ja kirjautua ulos, näyttää käyttäjätietoja hallintapaneelissa ja lisätä todentamistuki taustakäyttöön.
Siirrytään Play-sovellukseemme ja toteutetaan sisäänkirjautumis- ja kirjautumistoiminnot. Lisää opinnäytetyöt riveihin ”Application.java”:
public class Secured extends Security.Authenticator { @Override public String getUsername(Context ctx) { return ctx.session().get('username'); } @Override public Result onUnauthorized(Context ctx) { return unauthorized(); } }
Seuraavaksi lisätään mahdollisuus sallia tietyt back-end-puhelut vain todennetuille käyttäjille. Luo ”Secured.java” seuraavalla koodilla:
yo angular:controller menu
Käytämme tätä luokkaa myöhemmin uusien toimien suojaamiseen. Seuraavaksi meidän tulisi säätää AngularJS-sovelluksen päävalikkoa siten, että siinä näkyy käyttäjänimi ja uloskirjautumislinkit. Tätä varten meidän on luotava ohjain:
// menu.js angular.module('clientApp') .controller('MenuCtrl', function ($scope, $http, userService, $location) { $scope.user = userService; $scope.logout = function() { $http.get('/app/logout') .success(function(data) { if(data.hasOwnProperty('success')) { userService.username = ''; $location.path('/login'); } }); }; $scope.$watch('user.username', function (newVal) { if(newVal === '') { $scope.isLoggedIn = false; } else { $scope.username = newVal; $scope.isLoggedIn = true; } }); });
yo angular:controller login yo angular:view login
Tarvitsemme myös näkymän ja ohjaimen kirjautumissivulle:
Email Password Log in
// login.js angular.module('clientApp') .controller('LoginCtrl', function ($scope, userService, $location, $log, $http, alertService) { $scope.isAuthenticated = function() { if(userService.username) { $log.debug(userService.username); $location.path('/dashboard'); } else { $http.get('/app/isauthenticated') .error(function() { $location.path('/login'); }) .success(function(data) { if(data.hasOwnProperty('success')) { userService.username = data.success.user; $location.path('/dashboard'); } }); } }; $scope.isAuthenticated(); $scope.login = function() { var payload = { email : this.email, password : this.password }; $http.post('/app/login', payload) .error(function(data, status){ if(status === 400) { angular.forEach(data, function(value, key) { if(key === 'email' || key === 'password') { alertService.add('danger', key + ' : ' + value); } else { alertService.add('danger', value.message); } }); } else if(status === 401) { alertService.add('danger', 'Invalid login or password!'); } else if(status === 500) { alertService.add('danger', 'Internal server error!'); } else { alertService.add('danger', data); } }) .success(function(data){ $log.debug(data); if(data.hasOwnProperty('success')) { userService.username = data.success.user; $location.path('/dashboard'); } }); }; });
Toggle Dropdown
{{ username }} Seuraavaksi muokkaamme valikkoa, jotta se voi näyttää käyttäjätiedot:
yo angular:view addpost
Jos kirjaudut sisään sovellukseen, sinun pitäisi pystyä näkemään seuraava näyttö:
Nyt kun meillä on perusrekisteröinti- ja todennusmekanismit, voimme siirtyä lähettämistoiminnon toteuttamiseen. Lisätään uusi näkymä ja ohjain viestien lisäämiseksi.
Subject Post Submit post
yo angular:controller addpost
// addpost.js angular.module('clientApp') .controller('AddpostCtrl', function ($scope, $http, alertService, $location) { $scope.post = function() { var payload = { subject : $scope.subject, content: $scope.content }; $http.post('/app/post', payload) .error(function(data, status) { if(status === 400) { angular.forEach(data, function(value, key) { if(key === 'subject' || key === 'content') { alertService.add('danger', key + ' : ' + value); } else { alertService.add('danger', value.message); } }); } else if(status === 401) { $location.path('/login'); } else if(status === 500) { alertService.add('danger', 'Internal server error!'); } else { alertService.add('danger', data); } }) .success(function(data) { $scope.subject = ''; $scope.content = ''; alertService.add('success', data.success.message); }); }; });
.when('/addpost', { templateUrl: 'views/addpost.html', controller: 'AddpostCtrl' })
Sitten päivitämme ”app.js” sisältämään:
Seuraavaksi muokkaamme hakemistoa index.html lisäämällä linkki “addpost” -näkymään hallintapaneelin valikossa:
// Post.java public class Post extends Controller { public static Result addPost() { Form postForm = Form.form(PostForm.class).bindFromRequest(); if (postForm.hasErrors()) { return badRequest(postForm.errorsAsJson()); } else { BlogPost newBlogPost = new BlogPost(); newBlogPost.commentCount = 0L; newBlogPost.subject = postForm.get().subject; newBlogPost.content = postForm.get().content; newBlogPost.user = getUser(); newBlogPost.save(); } return ok(Application.buildJsonResponse('success', 'Post added successfully')); } private static User getUser() { return User.findByEmail(session().get('username')); } public static class PostForm { @Constraints.Required @Constraints.MaxLength(255) public String subject; @Constraints.Required public String content; } }
Luo nyt Play-sovelluksen puolella uusi ohjainviesti AddPost-menetelmällä:
POST /app/post controllers.Post.addPost
Lisää uusi merkintä reittitiedostoon voidaksesi käsitellä uusia menetelmiä reitityksessä:
// Application.java public static Result getPosts() { return ok(Json.toJson(BlogPost.find.findList())); }
Tässä vaiheessa sinun pitäisi pystyä lisäämään uusia viestejä.
Viestien lisääminen on vain vähän arvoa, jos emme voi näyttää niitä. Haluamme tehdä luettelon kaikista pääsivun viesteistä. Aloitamme lisäämällä uusi menetelmä sovellusohjaimeemme:
GET /app/posts controllers.Application.getPosts
Ja rekisteröimällä se reittitiedostoon:
// main.js angular.module('clientApp') .controller('MainCtrl', function ($scope, $http) { $scope.getPosts = function() { $http.get('app/posts') .success(function(data) { $scope.posts = data; }); }; $scope.getPosts(); });
Seuraavaksi muokkaamme AngularJS-sovelluksessamme pääohjainta:
{{ post.subject }}
{{ post.content }}
Post by: {{ post.user.email }} | Comments {{ post.commentCount }}
Poista lopuksi kaikki tiedostosta “main.html” ja lisää tämä:
yo angular:controller viewpost yo angular:view viewpost
Jos lataat sovelluksen etusivun, sinun pitäisi nähdä jotain samanlaista kuin tämä:
Meillä pitäisi myös olla erillinen näkymä yksittäisille viesteille.
// viewpost.js angular.module('clientApp') .controller('ViewpostCtrl', function ($scope, $http, alertService, userService, $location) { $scope.user = userService; $scope.params = $routeParams; $scope.postId = $scope.params.postId; $scope.viewPost = function() { $http.get('/app/post/' + $scope.postId) .error(function(data) { alertService.add('danger', data.error.message); }) .success(function(data) { $scope.post = data; }); }; $scope.viewPost(); });
{{ post.subject }}
{{ post.content }}
Post by: {{ post.user.email }} | Comments {{ post.commentCount }}
app.js: .when('/viewpost/:postId', { templateUrl: 'views/viewpost.html', controller: 'ViewpostCtrl' })
Ja AngularJS-reitti:
// Application.java public static Result getPost(Long id) { BlogPost blogPost = BlogPost.findBlogPostById(id); if(blogPost == null) { return notFound(buildJsonResponse('error', 'Post not found')); } return ok(Json.toJson(blogPost)); }
Kuten aikaisemmin, lisäämme uuden menetelmän sovellusohjaimeemme:
GET /app/post/:id controllers.Application.getPost(id: Long)
… Ja uusi reitti:
// dashboard.js angular.module('clientApp') .controller('DashboardCtrl', function ($scope, $log, $http, alertService, $location) { $scope.loadPosts = function() { $http.get('/app/userposts') .error(function(data, status) { if(status === 401) { $location.path('/login'); } else { alertService.add('danger', data.error.message); } }) .success(function(data) { $scope.posts = data; }); }; $scope.loadPosts(); });
Jos nyt siirryt osoitteeseen http: // localhost: 9000 / # / viewpost / 1, voit ladata näkymän tietylle postaukselle. Lisätään seuraavaksi mahdollisuus nähdä käyttäjän viestit hallintapaneelissa:
My Posts
No posts yet. Add a post {{ post.subject }} | Comments {{ post.commentCount }}
// Post.java public static Result getUserPosts() { User user = getUser(); if(user == null) { return badRequest(Application.buildJsonResponse('error', 'No such user')); } return ok(Json.toJson(BlogPost.findBlogPostsByUser(user))); }
Lisää myös uusi menetelmä Post-ohjaimeen ja seuraa tätä menetelmää vastaava reitti:
GET /app/userposts controllers.Post.getUserPosts
// Post.java public static Result addComment() { Form commentForm = Form.form(CommentForm.class).bindFromRequest(); if (commentForm.hasErrors()) { return badRequest(commentForm.errorsAsJson()); } else { PostComment newComment = new PostComment(); BlogPost blogPost = BlogPost.findBlogPostById(commentForm.get().postId); blogPost.commentCount++; blogPost.save(); newComment.blogPost = blogPost; newComment.user = getUser(); newComment.content = commentForm.get().comment; newComment.save(); return ok(Application.buildJsonResponse('success', 'Comment added successfully')); } } public static class CommentForm { @Constraints.Required public Long postId; @Constraints.Required public String comment; }
Kun luot viestit, ne näkyvät hallintapaneelissa:
Kommentointitoiminnon toteuttamiseksi aloitamme lisäämällä uuden menetelmän Post-ohjaimeen:
POST /app/comment controllers.Post.addComment
Ja kuten aina, meidän on rekisteröitävä uusi reitti tälle menetelmälle:
$scope.addComment = function() { var payload = { postId: $scope.postId, comment: $scope.comment }; $http.post('/app/comment', payload) .error(function(data, status) { if(status === 400) { angular.forEach(data, function(value, key) { if(key === 'comment') { alertService.add('danger', key + ' : ' + value); } else { alertService.add('danger', value.message); } }); } else if(status === 401) { $location.path('/login'); } else if(status === 500) { alertService.add('danger', 'Internal server error!'); } else { alertService.add('danger', data); } }) .success(function(data) { alertService.add('success', data.success.message); $scope.comment = ''; $scope.viewPost(); }); };
AngularJS-sovelluksessamme lisätään seuraava ”viewpost.js”:
By: {{ comment.user.email }}
{{ comment.content }} Login to comment
Add comment
Comment Add comment
Ja lisää lopuksi seuraavat rivit ”viewpost.html”:
|_+_|
Jos avaat minkä tahansa viestin, voit lisätä ja tarkastella kommentteja.
Tässä opetusohjelmassa olemme rakentaneet AngularJS-blogin, jossa Play-sovellus toimii REST-sovellusliittymän taustana. Vaikka sovelluksesta puuttuu vankka tietojen vahvistus (etenkin asiakaspuolella) ja suojaus, nämä aiheet eivät kuuluneet tämän opetusohjelman piiriin. Sen tarkoituksena oli osoittaa yksi monista mahdollisista tavoista rakentaa tällainen sovellus. Mukavuuden vuoksi tämän sovelluksen lähdekoodi on ladattu GitHub-arkisto .
Jos tämä AngularJS- ja Play-yhdistelmä on mielestäsi mielenkiintoinen, suosittelen, että tarkastelet seuraavia aiheita tarkemmin: