How to use functions, events and html DOM in ember?

Hi everyone! I,m studying Ember, and I have a few questions to understand the basic principles. I believe that this concerns the key points. Let me show you a little code, which is the boilerplate for me with typical tasks. There is an onclick functions, data recieving from JSON, change an attributes of html using the received data. These are the tasks that I want to understand most of all, and I will be very grateful to you for any help! Please tell me how to implement all of this in the spirit of Ember? I need to get the same result that will be reused in several routes, that is, different JSON will be processed. Perhaps the code should be contained in the component, but I could be wrong. I really like Ember, everything is in its place here, and I really would like to figure out in which parts of Ember it needs to be separated (for example, the hbs template, the route and other parts that are needed), so what where should be placed. I find it difficult to explain, but I think you will understand me. Great thanks in advance for any help! Excuse me my french :slightly_smiling_face:

Here is listing:

<!DOCTYPE html>
<html lang="en">

<body>
  <script src="data.json"></script>

  <div class="container">
    <div class="wrapper">
      <div id="items" style="display: flex; justify-content: space-between;">
        <div id="a" onclick="getData(this.id)" style="width: 100px; height: 100px; background-color: coral"></div>
        <div id="b" onclick="getData(this.id)" style="width: 100px; height: 100px; background-color: coral"></div>
        <div id="c" onclick="getData(this.id)" style="width: 100px; height: 100px; background-color: coral"></div>
        <div id="d" onclick="getData(this.id)" style="width: 100px; height: 100px; background-color: coral"></div>
        <div id="e" onclick="getData(this.id)" style="width: 100px; height: 100px; background-color: coral"></div>
      </div>

      <br><br>

      <select name="getValues" id="getValues" style="display: block;">
        <option value="first">First values</option>
        <option value="second">Second values</option>
      </select>

      <br><br>

      <button onclick="setData()" class="waves-effect waves-light btn-large xbutton">SELECT</button>
    </div>
  </div>


  <script> 
    function getData(clicked_id) {
      let selectValue = document.getElementById("getValues").value;
      alert("Value = " + parseFloat(data[selectValue][clicked_id]));
    }

    function setData() {
      let selectValue = document.getElementById("getValues").value;
      for (x in data[selectValue]) {
        let n = data[selectValue][x];
        if (n < 15)
          document.getElementById(x).style.backgroundColor = "red";
        if (n >= 15 && n < 50)
          document.getElementById(x).style.backgroundColor = "green";
        if (n >= 50 && n < 100)
          document.getElementById(x).style.backgroundColor = "blue";
        if (n >= 100)
          document.getElementById(x).style.backgroundColor = "yellow";
      }
    }
  </script>
</body>

</html>

Here is JSON file:

var data = {
  "first": {
    "a": 14,
    "b": 37,
    "c": 117,
    "d": 893,
    "e": 11
  },
  "second": {
    "a": 89,
    "b": 777,
    "c": 9,
    "d": 3,
    "e": 57
  }
};

Hi @Nar_Zantaria. There’s a lot going on here that makes it hard to focus on one piece at a time. I’ll start with a high level summary:

  1. Make a new ember app with ember new my-app. All the other files I mention here will be inside that project. cd my-app and run ember s to start the development server. You will see the welcome message at http://localhost:4200.

  2. Your json file isn’t really a json file, it’s a javascript file. The confusion between the two may give you trouble. You’re currently loading it as a <script> but that won’t work for a real json file. I’m going to assume we’re using a valid json file and I’ll put it into public/fixed-data.json:

    {
      "first": {
        "a": 14,
        "b": 37,
        "c": 117,
        "d": 893,
        "e": 11
      },
      "second": {
        "a": 89,
        "b": 777,
        "c": 9,
        "d": 3,
        "e": 57
      }
    }
    

    The public folder is where you can put any files inside an Ember app that you want to publicly available, unchanged, in the final application.

  3. I will assume we want to put this demo onto the “homepage” of our application, so I’m going to work in the application route, which is the very topmost / main route that always renders in an Ember application. (Later in a real application you will probably want to move this onto some other route, so you can have different routes display different things.)

  4. To load the data, make a Route file named app/routes/application.js like this:

    import Route from '@ember/routing/route';
    
    export default Route.extend({
      async model() {
        return (await fetch('/data.json')).json();
      }
    });
    
  5. Then edit app/templates/application.hbs. You can remove the initial content that’s in there about <WelcomePage />. First, let’s just make sure our data is loaded correctly by printing it out:

    {{#each-in model as |section value|}}
      <h1>{{section}}</h1>
      {{#each-in value as |name count|}}
        <div>{{name}}={{count}}</div>
      {{/each-in}}
    {{/each-in}}
    

    You should now see your data printed in the browser. The model here corresponds with the model in app/routes/application.js. It holds your data. The rest of that snippet is just iterating over both levels of your file and printing out the values.

  6. Next, instead of just printing the data we’re going to pass it into a component (we didn’t make the component yet, that will be the next step). Add this to to app/templates/application.hbs:

    <ColorDemo @data={{model}} />
    
  7. Now we need to make the component. You can run ember generate component color-demo in the terminal to get the files created automatically, or you can make them by hand. Here is the template file (app/templates/components/color-demo.hbs), which I based on your original HTML:

     <div class="container">
       <div class="wrapper">
         <div id="items" style="display: flex; justify-content: space-between;">
           {{#each-in this.items as |id value|}}
             <div onclick={{action this.showIt value}} style="width: 100px; height: 100px; background-color: coral"></div>
           {{/each-in}}
         </div>
    
         <br><br>
    
         <select onchange={{action this.changeSection}} style="display: block;">
           <option value="first" selected>First values</option>
           <option value="second">Second values</option>
         </select>
    
       </div>
     </div>
    

    And here is the Javascript file (app/components/color-demo.js):

     import Component from '@ember/component';
     import { computed } from '@ember/object';
    
     export default Component.extend({
       section: 'first',
       items: computed('section', 'data', function() {
         return this.data[this.section];
       }),
       changeSection(event) {
         this.set('section', event.target.value);
       },
       showIt(value) {
         alert("Value = " + value);
       }
     });
    
    

    At this point it does everything except change the colors based on the data. For that, I’m going to make a separate helper function.

  8. Make a helper app/helpers/style-for-value.js:

     import { helper } from "@ember/component/helper";
     import { htmlSafe } from '@ember/template';
    
     export function colorForValue([n]) {
       let color;
       if (n < 15) {
         color = "red";
       }
       if (n >= 15 && n < 50) {
         color = "green";
       }
       if (n >= 50 && n < 100) {
         color = "blue";
       }
       if (n >= 100) {
         color = "yellow";
       }
       return htmlSafe(`width: 100px; height: 100px; background-color: ${color}`);
     }
    
     export default helper(colorForValue);
    
  9. Then we will use the helper function. Change the template from this:

    <div onclick={{action this.showIt value}} style="width: 100px; height: 100px; background-color: 
    coral"></div>
    

    To this:

     <div onclick={{action this.showIt value}} style={{style-for-value value}}></div>
    
2 Likes