ember-cli
, provides access to the many features of this framework. Ember-cli
supports the programmer at all stages of work. It simplifies creating an application, extending its functionality, testing and launching a project in development mode.ember-cli
. Therefore it is important to study this tool. We, in the course of work on the educational project, will constantly use it.ember-cli
, or, if it is already installed, to check the relevance of the existing version. You can install ember-cli
from the npm
registry with the following command: $ npm install -g ember-cli
ember-cli
installed, you can use the following command: $ ember --version ember-cli: 2.15.0-beta.1 node: 8.2.1 os: darwin x64
ember-cli
installed, we are ready to start creating the application. This is the first situation in which we will use ember-cli
. He creates the structure of the application, customizes it and gives us a working project. Create a dice-roller
application with the following command: $ ember new dice-roller installing app create .editorconfig create .ember-cli create .eslintrc.js create .travis.yml create .watchmanconfig create README.md create app/app.js create app/components/.gitkeep create app/controllers/.gitkeep create app/helpers/.gitkeep create app/index.html create app/models/.gitkeep create app/resolver.js create app/router.js create app/routes/.gitkeep create app/styles/app.css create app/templates/application.hbs create app/templates/components/.gitkeep create config/environment.js create config/targets.js create ember-cli-build.js create .gitignore create package.json create public/crossdomain.xml create public/robots.txt create testem.js create tests/.eslintrc.js create tests/helpers/destroy-app.js create tests/helpers/module-for-acceptance.js create tests/helpers/resolver.js create tests/helpers/start-app.js create tests/index.html create tests/integration/.gitkeep create tests/test-helper.js create tests/unit/.gitkeep create vendor/.gitkeep NPM: Installed dependencies Successfully initialized git. $
yarn
can be used instead of the package manager npm
. Details on this can be found in the Ember documentation.ember-cli
. This is done like this: $ cd dice-roller $ ember serve Livereload server on http://localhost:49153 'instrument' is imported from external module 'ember-data/-debug' but never used Warning: ignoring input sourcemap for vendor/ember/ember.debug.js because ENOENT: no such file or directory, open '/Users/coxg/source/me/writing/repos/dice-roller/tmp/source_map_concat-input_base_path-2fXNPqjl.tmp/vendor/ember/ember.debug.map' Warning: ignoring input sourcemap for vendor/ember/ember-testing.js because ENOENT: no such file or directory, open '/Users/coxg/source/me/writing/repos/dice-roller/tmp/source_map_concat-input_base_path-Xwpjztar.tmp/vendor/ember/ember-testing.map' Build successful (5835ms) – Serving on http://localhost:4200/ Slowest Nodes (totalTime => 5% ) | Total (avg) ----------------------------------------------+--------------------- Babel (16) | 4625ms (289 ms) Rollup (1) | 445ms
app/templates/application.hbs
to the following form: This is my new application. {{outlet}}
{{outlet}}
tag is part of how the routing process works in Ember. We'll talk more about this below.ember-cli
in the ember-cli
. It should look something like this: file changed templates/application.hbs Build successful (67ms) – Serving on http://localhost:4200/ Slowest Nodes (totalTime => 5% ) | Total (avg) ----------------------------------------------+--------------------- SourceMapConcat: Concat: App (1) | 9ms SourceMapConcat: Concat: Vendor /asset... (1) | 8ms SimpleConcatConcat: Concat: Vendor Sty... (1) | 4ms Funnel (7) | 4ms (0 ms)
LiveReload
installed and running, then you do not even need to manually reload the page in order to see the changes. Otherwise, the application page will have to reload on its own. $ ember test ⠸ Building'instrument' is imported from external module 'ember-data/-debug' but never used ⠴ BuildingWarning: ignoring input sourcemap for vendor/ember/ember.debug.js because ENOENT: no such file or directory, open '/Users/coxg/source/me/writing/repos/dice-roller/tmp/source_map_concat-input_base_path-S8aQFGaz.tmp/vendor/ember/ember.debug.map' ⠇ BuildingWarning: ignoring input sourcemap for vendor/ember/ember-testing.js because ENOENT: no such file or directory, open '/Users/coxg/source/me/writing/repos/dice-roller/tmp/source_map_concat-input_base_path-wO8OLEE2.tmp/vendor/ember/ember-testing.map' cleaning up... Built project successfully. Stored in "/Users/coxg/source/me/writing/repos/dice-roller/tmp/class-tests_dist-PUnMT5zL.tmp". ok 1 PhantomJS 2.1 - ESLint | app: app.js ok 2 PhantomJS 2.1 - ESLint | app: resolver.js ok 3 PhantomJS 2.1 - ESLint | app: router.js ok 4 PhantomJS 2.1 - ESLint | tests: helpers/destroy-app.js ok 5 PhantomJS 2.1 - ESLint | tests: helpers/module-for-acceptance.js ok 6 PhantomJS 2.1 - ESLint | tests: helpers/resolver.js ok 7 PhantomJS 2.1 - ESLint | tests: helpers/start-app.js ok 8 PhantomJS 2.1 - ESLint | tests: test-helper.js 1..8 # tests 8 # pass 8 # skip 0 # fail 0 # ok
ember new
creates the necessary folders and files for the application, which are quite a few. Understanding how it all works is important for organizing effective work with Ember and for creating projects of any scale.npm
configuration file that describes the application. It is mainly used to ensure correct installation of dependencies.ember-cli
that is responsible for building the application.npm
or Bower
to install the required package.app/index.html
, which describes the structure of the main page in which the application is displayed. We are going to add CDN links to jQuery, to the font with Google icons, and to Materialize. <!-- Inside the Head section --> <link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet"> <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.1/css/materialize.min.css"> <!-- Inside the Body section --> <script type="text/javascript" src="https://code.jquery.com/jquery-3.2.1.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.1/js/materialize.min.js"></script>
app/templates/application.hbs
file to this form: <nav> <div class="nav-wrapper"> <a href="#" class="brand-logo"> <i class="material-icons">filter_6</i> Dice Roller </a> <ul id="nav-mobile" class="right hide-on-med-and-down"> </ul> </div> </nav> <div class="container"> {{outlet}} </div>
{{outlet}}
tag mentioned above is located.{{outlet}}
tag. Ember's job is route based. Each route is considered a descendant of some other route. The root route is processed automatically, it displays the app/templates/application.hbs
.{{outlet}}
tag specifies the place where Ember will display the contents corresponding to the next route in the current hierarchy - as a result, the first level route is displayed in this tag in application.hbs
, the second level route is displayed in the same tag in the first level template, and so Further.ember-cli
: $ ember generate route roll installing route create app/routes/roll.js create app/templates/roll.hbs updating router add route roll installing route-test create tests/unit/routes/roll-test.js
app/routes/roll.js
app/templates/roll.hbs
is app/templates/roll.hbs
.tests/unit/routes/roll-test.js
app/router.js
app/templates/roll.hbs
: <div class="row"> <form class="col s12"> <div class="row"> <div class="input-field col s12"> <input placeholder="Name" id="roll_name" type="text" class="validate"> <label for="roll_name">Name of Roll</label> </div> </div> <div class="row"> <div class="input-field col s6"> <input placeholder="Number of dice" id="number_of_dice" type="number" class="validate" value="1"> <label for="number_of_dice">Number of Dice</label> </div> <div class="input-field col s6"> <input placeholder="Number of sides" id="number_of_sides" type="number" class="validate" value="6"> <label for="number_of_sides">Number of Sides</label> </div> </div> <div class="row"> <button class="btn waves-effect waves-light" type="submit" name="action"> Roll Dice <i class="material-icons right">send</i> </button> </div> </form> </div> {{outlet}}
link-to
tag. It, among other things, accepts the name of the route that we are sending the user, and displays the elements that allow the user to go on this route.app/templates/application.hbs
file: <ul id="nav-mobile" class="right hide-on-med-and-down"> {{#link-to 'roll' tagName="li"}} <a href="roll">Roll Dice</a> {{/link-to}} </ul>
Roll Dice
, appeared on the right side of the panel, when the user clicks on the /roll
route. That is what we tried to achieve./roll
link works, but the field signatures on the form are incorrectly aligned. This is due to the fact that Materialize needs to call a certain JS-code in order to arrange the elements accordingly, but due to the nature of dynamic routing, the pages are not reloaded. Now we fix it.Roll Dice
form. As usual in such situations, to create a component, let's turn to ember-cli
: $ ember generate component roll-dice installing component create app/components/roll-dice.js create app/templates/components/roll-dice.hbs installing component-test create tests/integration/components/roll-dice-test.js
app/components/roll-dice.js
app/templates/components/roll-dice.hbs
tests/integration/components/roll-dice-test.js
app/templates/components/roll-dice.hbs
to this state: <form class="col s12"> <div class="row"> <div class="input-field col s12"> <input placeholder="Name" id="roll_name" type="text" class="validate"> <label for="roll_name">Name of Roll</label> </div> </div> <div class="row"> <div class="input-field col s6"> <input placeholder="Number of dice" id="number_of_dice" type="number" class="validate" value="1"> <label for="number_of_dice">Number of Dice</label> </div> <div class="input-field col s6"> <input placeholder="Number of sides" id="number_of_sides" type="number" class="validate" value="6"> <label for="number_of_sides">Number of Sides</label> </div> </div> <div class="row"> <button class="btn waves-effect waves-light" type="submit" name="action"> Roll Dice <i class="material-icons right">send</i> </button> </div> </form>
app/templates/roll.hbs
: <div class="row"> {{roll-dice}} </div> {{outlet}}
roll-dice
tag tells Ember where to put the component.didRender
hook, which is called after the component is displayed on the screen. Moreover, this is done both at the first show of the component, and at its subsequent shows.app/components/roll-dice.js
: /* global Materialize:false */ import Ember from 'ember'; export default Ember.Component.extend({ didRender() { Materialize.updateTextFields(); } });
/roll
route using a direct link or a link from the navigation bar, this code is executed, and Materialize correctly displays the text field labels.Component
class. Knowing this, we can use auxiliary tools that allow us to display the input fields for the component and bind these fields to the component variables. As a result, you can interact with the data directly, without thinking about working with the DOM.app/components/roll-dice.js
, inside the component definition block: rollName: '', numberOfDice: 1, numberOfSides: 6,
<input>
with the following code: <div class="row"> <div class="input-field col s12"> <!-- This replaces the <input> tag for "roll_name" --> {{input placeholder="Name" id="roll_name" class="validate" value=(mut rollName)}} <label for="roll_name">Name of Roll</label> </div> </div> <div class="row"> <div class="input-field col s6"> <!-- This replaces the <input> tag for "number_of_dice" --> {{input placeholder="Number of dice" id="number_of_dice" type="number" class="validate" value=(mut numberOfDice)}} <label for="number_of_dice">Number of Dice</label> </div> <div class="input-field col s6"> <!-- This replaces the <input> tag for "number_of_sides" --> {{input placeholder="Number of sides" id="number_of_sides" type="number" class="validate" value=(mut numberOfSides)}} <label for="number_of_sides">Number of Sides</label> </div> </div>
value
attribute looks unusual. Similar constructions can be used for any attribute of the tag, and not just for value
. Here are three ways to use them:(mut <name>)
. Due to this, the corresponding value is taken from the component, and the component changes (mutate) as the value changes in the browser.Roll Dice
. Ember (Actions). — , . — , , , , actions
.OnSubmit
. , , Enter
.app/components/roll-dice.hbs
: actions: { triggerRoll() { alert(`Rolling ${this.numberOfDice}D${this.numberOfSides} as "${this.rollName}"`); return false; } }
false
. — , HTML-. .onsubmit
. Ember . app/templates/components/roll-dice.hbs
: <form class="col s12" onsubmit={{action 'triggerRoll'}}>
app/routes/roll.js
, , , . actions: { saveRoll: function(rollName, numberOfDice, numberOfSides) { alert(`Rolling ${numberOfDice}D${numberOfSides} as "${rollName}"`); } }
app/components/roll-dice.js
, . sendAction
: triggerRoll() { this.sendAction('roll', this.rollName, this.numberOfDice, this.numberOfSides); return false; }
app/templates/roll.hbs
. , : {{roll-dice roll="saveRoll" }}
roll
saveRoll
. , roll
, , , «» . , , «» , , .ember-cli
. $ ember generate model roll installing model create app/models/roll.js installing model-test create tests/unit/models/roll-test.js
app/models/roll.js
: import DS from 'ember-data'; export default DS.Model.extend({ rollName: DS.attr('string'), numberOfDice: DS.attr('number'), numberOfSides: DS.attr('number'), result: DS.attr('number') });
DS.attr
. — string
, number
, date
boolean
, , .app/routes/roll.js
: saveRoll: function(rollName, numberOfDice, numberOfSides) { let result = 0; for (let i = 0; i < numberOfDice; ++i) { result += 1 + (parseInt(Math.random() * numberOfSides)); } const store = this.get('store'); // "roll" . const roll = store.createRecord('roll', { rollName, numberOfDice, numberOfSides, result }); // , . roll.save(); }
Roll Dice
. , , , , , — .index
— .index
, . , , , . «» .index
, ember-cli
. .app/routes/index.js
, : import Ember from 'ember'; export default Ember.Route.extend({ model() { return this.get('store').findAll('roll'); } });
findAll
«» . , model
.app/templates/index.hbs
: <table> <thead> <tr> <th>Name</th> <th>Dice Rolled</th> <th>Result</th> </tr> </thead> <tbody> {{#each model as |roll|}} <tr> <td>{{roll.rollName}}</td> <td>{{roll.numberOfDice}}D{{roll.numberOfSides}}</td> <td>{{roll.result}}</td> </tr> {{/each}} </tbody> </table> {{outlet}}
ember-cli
— , . , , Ember , .Source: https://habr.com/ru/post/341076/
All Articles