|
1 | 1 | ## Tutorials |
2 | 2 | If you aren't familiar with the semantic.works stack/microservices yet, you might want to check out [why semantic tech?](https://mu.semte.ch/2017/03/23/adding-ember-fastboot-to-your-mu-project/) |
3 | 3 |
|
| 4 | +Each of these tutorials starts with a mu-project docker-compose set-up. |
| 5 | + |
4 | 6 | - [Creating a JSON API](#creating-a-json-api) |
| 7 | +- [Adding an ember UI to your project](#adding-an-ember-ui-to-your-project) |
5 | 8 | - [Adding authentication to your mu-project](#adding-authentication-to-your-mu-project) |
6 | 9 | - [Creating a mail service](#building-a-mail-handling-service) |
7 | 10 | - [Adding Ember Fastboot to your project](#adding-ember-fastboot-to-your-project) |
@@ -210,6 +213,162 @@ That's it! Now you can [fetch](http://jsonapi.org/format/#fetching-relationships |
210 | 213 | *This tutorial has been adapted from Erika Pauwels' mu.semte.ch articles. You can view them [here](https://mu.semte.ch/2017/07/27/generating-a-jsonapi-compliant-api-for-your-resources/) and [here](https://mu.semte.ch/2017/08/17/generating-a-jsonapi-compliant-api-for-your-resources-part-2/).* |
211 | 214 |
|
212 | 215 |
|
| 216 | +### Adding an ember UI to your project |
| 217 | +This tutorial builds on the [previous one](#creating-a-json-api) to add a UI to manage books using [EmberJS](https://www.emberjs.com/). |
| 218 | + |
| 219 | +#### Ember in the frontend |
| 220 | + |
| 221 | +Our end-users access the services through EmberJS application. This provides us with an integrated, styled and flexible view of the enabled microservices. We’ll create a new ember application to allow end-users to list, create, and delete authors. The advised way to build and develop EmberJS applications is using ember-cli. |
| 222 | + |
| 223 | +You can install ember-cli from ember-cli.com, or you can use the ember-docker found at https://github.com/madnificent/docker-ember . Our examples assume you’ll use ember-docker. |
| 224 | + |
| 225 | +#### Build a new app |
| 226 | + |
| 227 | +First we create the new application. The command is short, but it may take a while to fetch all NPM dependencies. Grab a coffee while the computer works for you. |
| 228 | + |
| 229 | +```sh |
| 230 | +edi ember new books |
| 231 | +``` |
| 232 | + |
| 233 | +#### Live reloading changes |
| 234 | + |
| 235 | +Let’s see if our new application runs. Go into the books directory and run the ember serve command (available as eds). Once the files have compiled, you can visit the site in your browser at localhost:4200. |
| 236 | + |
| 237 | +```sh |
| 238 | +cd books |
| 239 | +eds --proxy http://host # alt: ember serve --proxy http://localhost:80/ |
| 240 | +``` |
| 241 | + |
| 242 | +The proxy connects to our localhost on port 80 (yes, it’s called host in the ember-docker, rather than localhost). We’ll use this later to fetch content from the microservices. Let’s alter the title of our application, the browser’s view will update automatically. Open app/application.hbs and change the following: |
| 243 | + |
| 244 | +```diff |
| 245 | +- {{!-- The following component displays Ember's default welcome message. --}} |
| 246 | +- {{welcome-page}} |
| 247 | +- {{!-- Feel free to remove this! --}} |
| 248 | ++ <h2 id="title">My books</h2> |
| 249 | +``` |
| 250 | + |
| 251 | +Boom, automatic updates in the browser. |
| 252 | + |
| 253 | +#### Connecting |
| 254 | + |
| 255 | +EmberJS applications roughly follow the Web-MVC pattern. The applications have a rigid folder-structure, most content being in the app folder. Ember-cli uses generators to generate basic stubs of content. We create the books model, route and controller using ember-cli. Check the helpers for ember generate model, ember generate route and ember generate controller, or the following: |
| 256 | + |
| 257 | +```sh |
| 258 | +edi ember generate model book title:string isbn:string |
| 259 | +edi ember generate route book |
| 260 | +edi ember generate controller book |
| 261 | +``` |
| 262 | + |
| 263 | +The terminal output shows the created and updated files. (note: generating new files can make watched files fail in Docker, just kill and restart eds should that happen.) |
| 264 | + |
| 265 | +We will fetch all books and render them in our template. In routes/book.js: |
| 266 | + |
| 267 | +```diff |
| 268 | += export default class BooksRoute extends Route { |
| 269 | ++ model(){ |
| 270 | ++ return this.store.findAll('book'); |
| 271 | ++ } |
| 272 | += } |
| 273 | +``` |
| 274 | + |
| 275 | +We’ll display the found records in our template so we’re able to see the created records later on. Add the following to templates/book.hbs |
| 276 | + |
| 277 | +```diff |
| 278 | ++ <ul> |
| 279 | ++ {{#each @model as |book|}} |
| 280 | ++ <li>{{book.title}} <small>{{book.isbn}}</small></li> |
| 281 | ++ {{/each}} |
| 282 | ++ </ul> |
| 283 | +``` |
| 284 | + |
| 285 | +#### Creating new books |
| 286 | + |
| 287 | +We’ll add a small input-form through which we can create new books at the bottom of our listing. Two input fields and a create button will suffice for our example. |
| 288 | + |
| 289 | +In the app/templates/book.hbs template, we’ll add our create fields and button: |
| 290 | + |
| 291 | +```diff |
| 292 | ++ <hr /> |
| 293 | ++ <form {{on "submit" this.createBook}} > |
| 294 | ++ <dl> |
| 295 | ++ <dt>Book title</dt> |
| 296 | ++ <dd> |
| 297 | ++ <Input @value={{this.newTitle}} |
| 298 | ++ @placeholder="Thinking Fast and Slow" /> |
| 299 | ++ </dd> |
| 300 | ++ <dt>ISBN</dt> |
| 301 | ++ <dd> |
| 302 | ++ <Input @value={{this.newIsbn}} |
| 303 | ++ @placeholder="978-0374533557" /> |
| 304 | ++ </dd> |
| 305 | ++ </dl> |
| 306 | ++ <button type="submit">Create</button> |
| 307 | ++ </form> |
| 308 | +``` |
| 309 | + |
| 310 | +We’ll add this action in the controller and make it create the new book. In app/controllers/book.hbs add the following: |
| 311 | + |
| 312 | +```diff |
| 313 | += import Controller from '@ember/controller'; |
| 314 | ++ import { action } from '@ember/object'; |
| 315 | ++ import { tracked } from '@glimmer/tracking'; |
| 316 | ++ import { inject as service } from '@ember/service'; |
| 317 | += |
| 318 | += export default class BooksController extends Controller { |
| 319 | ++ @tracked newTitle = ''; |
| 320 | ++ @tracked newIsbn = ''; |
| 321 | ++ |
| 322 | ++ @service store; |
| 323 | ++ |
| 324 | ++ @action |
| 325 | ++ createBook(event) { |
| 326 | ++ event.preventDefault(); |
| 327 | ++ // create the new book |
| 328 | ++ const book = this.store.createRecord('book', { |
| 329 | ++ title: this.newTitle, |
| 330 | ++ isbn: this.newIsbn |
| 331 | ++ }); |
| 332 | ++ book.save() |
| 333 | ++ // clear the input fields |
| 334 | ++ this.newTitle = ''; |
| 335 | ++ this.newIsbn = ''; |
| 336 | ++ } |
| 337 | += }); |
| 338 | +``` |
| 339 | + |
| 340 | +#### Removing books |
| 341 | + |
| 342 | +Removing books follows a similar path to creating new books. We add a delete button to the template, and a delete action to the controller. |
| 343 | + |
| 344 | +In app/templates/book.hbs we alter: |
| 345 | + |
| 346 | +```diff |
| 347 | += <ul> |
| 348 | += {{#each @model as |book|}} |
| 349 | ++ <li> |
| 350 | ++ {{book.title}}<small>{{book.isbn}}</small> |
| 351 | ++ <button {{on "click" (fn this.removeBook book)}}>Remove</button> |
| 352 | ++ </li> |
| 353 | += {{/each}} |
| 354 | += </ul> |
| 355 | +``` |
| 356 | + |
| 357 | +In app/controllers/book.hbs we alter: |
| 358 | + |
| 359 | +```diff |
| 360 | += this.newTitle = ''; |
| 361 | += this.newIsbn = ''; |
| 362 | += } |
| 363 | ++ |
| 364 | ++ @action |
| 365 | ++ removeBook( book, event ) { |
| 366 | ++ event.preventDefault(); |
| 367 | ++ book.destroyRecord(); |
| 368 | += } |
| 369 | += } |
| 370 | +``` |
| 371 | + |
213 | 372 | ### Adding authentication to your mu-project |
214 | 373 |  |
215 | 374 |
|
|
0 commit comments