jeudi 30 septembre 2021

EmberJS Octane Avoid two way binding for @tracked variable and normal variable

In EmberJS if I assign a @tracked variable as the value of a second variable, updating the second variable also updates the tracked variable.

For example:

  @tracked
  baseProperty = this.args.baseProperty;

  @action
  updateDescription(event){
    let newProperty = this.baseProperty;
    let text = event.target.innerText;

    this.newProperty = Object.assign(this.newProperty , { property: htmlSafe(event.target.innerText) });
  }

If updateDescription() runs property for the newProperty object is updated, but property for the tracked baseProperty is updated as well. Is there a way to make it so that only newProperty updates?




mardi 28 septembre 2021

Emberjs Model from route returning undefined in controller

I have a strange behavior with my Ember app. I can't make any sense out of it. Basically I'm using Ember octane and I wanted to access my model from my route to my controller .

This is my route

import Route from '@ember/routing/route';

export default class ChatIndexRoute extends Route {
  model() {
    return {
      chatMessages: [
        {
          username: '1',
          message: 'Hi',
          read: true,
        },
        {
          username: '1',
          message: 'how are you?',
          read: false,
        },
        {
          username: '1',
          message: 'its been a long time :)',
          read: false,
        },
      ],
    };
  }

  setupController(controller, model) {
    controller.set('model', model.chatMessages);
  }
}

and this is my controller

import Controller from '@ember/controller';


export default class ChatIndexController extends Controller {
  init() {
    super.init(...arguments);
    console.log('test', this.model);
  }
}

When I console.log(this.model) I got undefined.

But when I simply do a console.log(this) I got a whole object with a model property filled with chatmessages

See this image

This is crazy




dimanche 26 septembre 2021

Ember Octane, Tracked property not rerendering template

Coming from a React background, I'm having issues understanding EmberJs "Tracked" concept. On paper it shouldn't be different from "React state".

So what I have understood is that when we anotate a property with @tracked it should cause a re render when there is a change in this property.

Please take a look at the code below:

ProductItemComponent

import Component from '@glimmer/component';
import { tracked } from '@glimmer/tracking';
import { inject as service } from '@ember/service';
import { action } from '@ember/object';

export default class ProductItemIndexComponent extends Component {
  @service('cart') cartService;

  @tracked addedToCart = false;

  @action
  checkItemInCart(id) {
    if (this.cartService.items.findBy('id', id)) {
      this.addedToCart = true;
    } else {
      this.addedToCart = false;
    }
  }
}

Template,

<div class="card-container">
  <div class="card product-item" >
    <img src= class="product-image card-img-top" alt="...">
    <div class="card-body">
      <h5></h5>
    </div>
    <div class="footer">
      <p class="card-text"><span class="badge badge-secondary"><strong>Price: </strong></span></p>
      <button type="button" class="btn btn-warning" 
        disabled=>Add
        to cart</button>
    </div>
  </div>
</div>

When I first render the component I'm checking if the current item is present in the cart using and if its present I'm switch the tracked property @tracked addedToCart = false; to true else false.

In theory, this should disable my button in my productItem template as soon as it finds the Item in the cartService. It only works when I go to another page and then come back.

But there is no rerender of the page. Can someone help me understand what I might be doing wrong?

Thank you in advance




mercredi 22 septembre 2021

Ember - How to break the build if test coverage fails minimum threshold?

I want to break the build if coverage drops below certain percentage. Currently test runs and coverage is generated if I run below command.

COVERAGE=true ember test

enter image description here

but I don't see a way to break the build based on coverage percentage. Request to help me on this.




lundi 20 septembre 2021

EmberJS Data Assert in setRecordDataFor "Illegal set of identifier"

Using 3.28 I am hitting an assert deep inside Ember Data when retrieving a relationship on one of my models. I can run the following query just fine:

return this.store.findRecord('project', project_id)

However when I run a subsequent

const monitors = await model.monitors;

in my afterModel() of the route, this assert is triggered.

My Models look pretty standard:

export default class ProjectModel extends Model {
  @attr('string') name;
  @belongsTo('user') creator;
  @attr('date') created;
  @attr('date') changed;
  @hasMany('domain-monitor') monitors;
}

export default class DomainMonitorModel extends Model {
  @belongsTo('project') project;
  @hasMany('page-monitor') pages;
  @attr('string') protocol;
  @attr('string') domain;
  @attr('date') created;
  @attr('date') changed;
}

If someone can point to what is going wrong, I am happy to submit an MR to improve this assert message to hopefully unstuck someone in the future. Thanks!




jeudi 16 septembre 2021

Ember-cli-build do not inject app.css into the compiled app

I just migrated my app from ember 2.18 to 3.4. I have a css file at app/styles/app.css

Here is my ember-cli-build.js

'use strict';

const EmberApp = require('ember-cli/lib/broccoli/ember-app');

module.exports = function(defaults) {
  let app = new EmberApp(defaults, {
    // Add options here
    adminLTE: {
      plugins: ['morris','datepicker',
        'bootstrap-wysihtml5', 'daterangepicker',
        'select2', 'input-mask'
      ]
    },

    flatpickr: {
      locales: ['fr']
    },

    minifyCSS: {
        enabled: true,
        options:
        {rebaseTo: 'assets'}
      },

    'ember-bootstrap': {
      bootstrapVersion: 3,
      importBootstrapCSS: false,
      importBootstrapFont: true
    }
  });
  return app.toTree();
};

And the relevant part of index.html :

    <link integrity="" rel="stylesheet" href="assets/vendor.css">
    <link integrity="" rel="stylesheet" href="assets/marketadmin.css">
    <link integrity="" rel="stylesheet" href="css/AdminLTE.min.css">
    <link integrity="" rel="stylesheet" href="css/skins/skin-blue.min.css">

There is no CSS rules of my app.css in vendor.css or in marketadmin.css. Why?




Eslint disable for a specific line pattern

Example, //test is a pattern used in one of my code processing to ignore some testing. And we matched exactly //test to exclude the processing. But when we apply Esline auto fix, //test automatically changes in // test (space added as formatting)

So, Extra processing is happening due to it.

Hence I had googled to fix this. possible solutions are,

  1. matching both patterns(//test & // test - this is out of my context, had to raise and wait for the fix)
  2. Or else, had to add eslint disable comment to disable eslint processing around that comments.

Is there any way to configure a line pattern to ignore commonly in .eslintrc.js? Curious to know about it. So far checked, there is a pattern to exclude file folder paths only.

Please let me know here if anyone knows about this(line pattern ignoring commonly)




lundi 13 septembre 2021

ember-cli-eslint - Unexpected top level property overrides[0].extends

I am having an issue with eslint (using ember-cli-eslint ver 5.1.0) and an extends property in my override in my .eslintrc file. My .eslintrc looks like this:

module.exports = {
    root: true,
    parser: 'babel-eslint',
    parserOptions: {
        ecmaVersion: 2018,
        sourceType: 'module',
        ecmaFeatures: {
            legacyDecorators: true
        }
    },
    plugins: [ 'ember' ],
    extends: [
        'eslint:recommended'
    ],
    env: {
        browser: true
    },
    overrides: [
        {
            files: [
                '.eslintrc.js',
                'ember-cli-build.js',
                'testem.js',
                'blueprints/*/index.js',
                'config/**/*.js',
                'lib/*/index.js'
            ],
            extends: [
                'plugin:my-plugin
            ]
        }
    ]
};

However when I build I get the following error:

ESLint configuration in path-to\my-app\.eslintrc.js is invalid:
        - Unexpected top-level property "overrides[0].extends".

I have another ember project with the same version of ember-cli-eslint and a very similar eslintrc file that uses the same extends property in overrides without issue. I have compared configurations between the two projects over and over and cannot figure out what is causing this. Doing research the most I could find is an issue that caused this error incorrectly on older versions of ember-cli-eslint, but that should be fixed in my version.

Am I missing a different configuration to allow extends properties in overrides?




jeudi 9 septembre 2021

How to send post request from form that sends the name, email and folder of the CV by using a method post in framework Ember?

How to send post request from form that sends the name, email and folder of the CV by using a method post in framework Ember




mercredi 8 septembre 2021

unable to import Braintree Javascript SDK in Ember "ember-cli": "^3.25.2",

I have installed the braintree package via npm, outlined here,

using

const braintree = require("braintree");

results in

loader.js:247 Uncaught Error: Could not find module braintree imported from (require)

attempting a manual install suggested here

app.import('node_modules/braintree/lib/braintree/braintree_gateway.js');

with

const braintree = require("braintree");

results

loader.js:247 Uncaught Error: Could not find module braintree imported from (require)

this

app.import('node_modules/braintree/lib/braintree.js');

results

card-payment.js:343 Uncaught TypeError: braintree.BraintreeGateway is not a constructor

grep -r BraintreeGateway node_modules/braintree/
node_modules/braintree/lib/braintree/braintree_gateway.js:class BraintreeGateway {
node_modules/braintree/lib/braintree/braintree_gateway.js:module.exports = {BraintreeGateway: BraintreeGateway};
node_modules/braintree/lib/braintree.js:let BraintreeGateway = require('./braintree/braintree_gateway').BraintreeGateway;
node_modules/braintree/lib/braintree.js:  BraintreeGateway: BraintreeGateway,
node_modules/braintree/CHANGELOG.md:* Add `GraphQLClient` to `BraintreeGateway` class
node_modules/braintree/README.md:var gateway = new braintree.BraintreeGateway({
node_modules/braintree/README.md:var gateway = new braintree.BraintreeGateway({

a grep of the node modules appears to show the last manual import as in the ballpark of correct.

component-class

  @action
  saveNonce() {
    // const braintree = require("braintree");

    var gateway = new braintree.BraintreeGateway({
      environment: String(ENV.BRAINTREE_ENVIRONMENT),
      merchantId: String(ENV.BRAINTREE_MERCHANT_ID),
      publicKey: String(ENV.BRAINTREE_PUBLIC_KEY),
      privateKey: String(ENV.BRAINTREE_PRIVATE_KEY)
    });

    let clientNonce = document.getElementById('save-nonce').value;

    gateway.transaction.sale({
      amount: String(this.amount/100),
      paymentMethodNonce: clientNonce,
      // deviceData: deviceDataFromTheClient,
      options: {
        submitForSettlement: true
      }
    }, (err, result) => {
    });

  }

package.json

...
"ember-cli": "^3.25.2",
"braintree": "^3.7.0",
...



How do you render and filter over a collection of data from an @argument?

This question comes from our Ember Discord


I have something like this


  <ItemList @categories=/>


I am calling action somewhere else, then filtering the @data and I would like to reset this each @data.

I want to assign the filtered result to @data data passed from parent component to this

At the same component I have button

<li 
  class="inline hover:underline cursor-pointer ml-4" 
  
>
  
</li>

and changeProject action filters the @data that I would like to re-assign to #each for example - this.data = filteredModel; does not work.




mardi 7 septembre 2021

Could not find module ember-routing/system/route

error while upgrading from 2.18 to 3.4

error while upgrading ember-CLI version from 2.18 to 3.4




Ember not displaying objects in views

I've started working on Discourse plugin and learning about Ember. I have 'keynote' model, which has 3 attributes: id, key, link. My problem is that when I create new keynote - it displays on keynotes page but if I reload page - results disappear. I'm sure that the problem in my fetch method. Here is my views page:

<button onclick="createKeynote">Create</button>
<form >
 <input type="text" id= key_area>
 <input type="text" id= link_area>

  <button type='submit' class='btn btn-primary'>
    
  </button>
</form>



<ul>
  
    <li>
       -->  ==> 
    </li>
  
</ul>

Here is the page for my keynotes controller:

 export default Ember.Controller.extend({
  init() {
    this._super();
    this.set('keynotes', []);
    this.fetchKeynotes();
  },

  fetchKeynotes() {
    this.store.findAll('keynote')
      .then(result => {
        for (const keynote of [result.link] && [result.key]) {
          this.keynotes.pushObject(keynote);
        }
      })
      .catch(console.error);
  },

  actions: {
    createKeynote(key, link)
    {
      key = document.getElementById("key_area").value
      link = document.getElementById("link_area").value
      const keynote_full = {};
      keynote_full[key] = link


      const keynoteRecord = this.store.createRecord('keynote', {
        id: Date.now(),
        key: key,
        link: link
      });
      console.log(keynoteRecord)

      keynoteRecord.save()
        .then(result => {
          this.keynotes.pushObject(result.target);
        })
        .catch(console.error);
    }
  }
});

Pay attention to 'fetchKeynotes' method - if I would try to console.log(findAll('keynote')) - it would give me out all attributes and also arrangedContent in which one contains all of the keynotes with all attributes (id, key, link), so as I said - I'm sure, that something is wrong with 'fetchKeynotes' method but I am not sure why.




lundi 6 septembre 2021

Check if value is false in handlebar helper

I have created a handlebar helper which gives true or false values. How can I check if the value is false and render HTML. I tried using unless but it's not working. I don't want to give any else condition.

ifTrue = false


   <p> Print when not true.</p>




samedi 4 septembre 2021

Ember.js Creating a new route in ember.js always lead to default index.html file

I am new at learning ember.js I have followed some tutorials but I don't know why It doesn't work for me. What I would like is to create a new route with games: http://localhost:4200/jeux so I have done :

ember g route jeux

To create a new route "/jeux" I have completed this new page with jeux.hbs:


<p>La page des jeux-vidéos</p>

Now I don't know why http://localhost:4200/jeux is still leading to the default index.html page [image of http://localhost:4200][1] [image of http://localhost:4200/jeux][2] Thanks for the Help! Here are some images that can help to understand my project (it is a simple project that I have generated with "ember new the project name")

[image of file "router.js"][3]
[basic default "index.html"][4]
[the evironment.js file][5]
[1]: https://i.stack.imgur.com/JAzuf.png
[2]: https://i.stack.imgur.com/LBrFB.png
[3]: https://i.stack.imgur.com/gQunM.png
[4]: https://i.stack.imgur.com/FEa93.png
[5]: https://i.stack.imgur.com/UaXfp.png



Ember.set not working on some specific property

I am not a beginner in Ember.js but I don't understand why the following bug occurs:

console.log('--> before set document', JSON.stringify(model.echographies));
model.echographies.pushObject(EmberObject.create({test: '1'}));
model.echographies.forEach(echography => {
  if (!echography.documents) {
    set(echography, 'documents', []); // <== bug is here
    set(echography, 'documentsX', []);
    set(echography, 'documentsY', 'test');
  }
});
console.log('--> after set document', JSON.stringify(model.echographies));

The output in the console is:

    --> before set document 
    [
        {"id":92,"echography_date":"2020-02","echography_freetext":"echography_freetext"}
    ]
    --> after set document 
    [
        {"id":92,"echography_date":"2020-02","echography_freetext":"echography_freetext","documentsX":[],"documentsY":"test"},
        {"test":"1","documents":[],"documentsX":[],"documentsY":"test"}
    ]

What I don't understand is why the documents property is not set on the real object while documentsX or documentsY work on it and why the three properties work on the fake object. I could not make a JSFiddle to reproduce the bug.

Ember 3.16 Objects are created with EmberObject.create. The array is displayed in the view with a and some computed watching the array.

Do you have any idea on why this bug could append? What should I try to debug this code and find why the set not working for this specific property?




braintree hosted payment fields client undefined Ember 3.25

Ember and Braintree Hosted Fields are not a good mix so far, Braintree Support are out of ideas on this one. When the form renders on the page it calls the action to create the client. The client is undefined. The live page is up here.

picture-this-44ac48bef9f8df633632a4d202da2379.js:57 Uncaught TypeError: Cannot read property 'client' of undefined

enter image description here

component hbs

<script src="https://js.braintreegateway.com/web/3.81.0/js/client.min.js"></script>
<script src="https://js.braintreegateway.com/web/3.81.0/js/hosted-fields.min.js"></script>
<div class="demo-frame" >
  <form action="/" method="post" id="cardForm" >
    <label class="hosted-fields--label" for="card-number">Card Number</label>
    <div id="card-number" class="hosted-field"></div>

    <label class="hosted-fields--label" for="expiration-date">Expiration Date</label>
    <div id="expiration-date" class="hosted-field"></div>

    <label class="hosted-fields--label" for="cvv">CVV</label>
    <div id="cvv" class="hosted-field"></div>

    <label class="hosted-fields--label" for="postal-code">Postal Code</label>
    <div id="postal-code" class="hosted-field"></div>

    <div class="button-container">
    <input type="submit" class="button button--small button--green" value="Purchase" id="submit"/>
    </div>
  </form>
</div>

component class

import Component from '@glimmer/component';
import { action } from '@ember/object';
import { inject as service } from '@ember/service';
import { tracked } from '@glimmer/tracking';
import { braintree } from 'braintree-web';

export default class CardPaymentComponent extends Component {

  @action
  setupBraintreeHostedFields() {

    alert('booh');
    var form = document.querySelector('#cardForm');
    var authorization = 'sandbox_24nzd6x7_gyvpsk2myght4c2p';

    braintree.client.create({
      authorization: authorization
    }, function(err, clientInstance) {
      if (err) {
        console.error(err);
        return;
      }
      createHostedFields(clientInstance);
    });

    function createHostedFields(clientInstance) {
      braintree.hostedFields.create({
        client: clientInstance,
        styles: {
          'input': {
            'font-size': '16px',
            'font-family': 'courier, monospace',
            'font-weight': 'lighter',
            'color': '#ccc'
          },
          ':focus': {
            'color': 'black'
          },
          '.valid': {
            'color': '#8bdda8'
          }
        },
        fields: {
          number: {
            selector: '#card-number',
            placeholder: '4111 1111 1111 1111'
          },
          cvv: {
            selector: '#cvv',
            placeholder: '123'
          },
          expirationDate: {
            selector: '#expiration-date',
            placeholder: 'MM/YYYY'
          },
          postalCode: {
            selector: '#postal-code',
            placeholder: '11111'
          }
        }
      }, function (err, hostedFieldsInstance) {
        var tokenize = function (event) {
          event.preventDefault();

          hostedFieldsInstance.tokenize(function (err, payload) {
            if (err) {
              alert('Something went wrong. Check your card details and try again.');
              return;
            }

            alert('Submit your nonce (' + payload.nonce + ') to your server here!');
          });
        };

        form.addEventListener('submit', tokenize, false);
      });
    }

  }

}

package.json

...
"ember-cli": "^3.25.2",
"braintree-web": "^3.81.0",
...



mercredi 1 septembre 2021

Add Extra Actions to LinkTo in Octane

I have a dropdown menu with links, when the links are clicked I'd like the menu to close.

Something like (a11y/i18n truncated):

<ul class="menu">
    <li>
        <LinkTo @route="myprofile">
            Profile
        </LinkTo>
    </li>
    <li>
        <LinkTo @route="logout">
            Logout
        </LinkTo>
    </li>
</ul>

I'd like to add an additional click handler to the link to, something like:

<ul class="menu">
    <li>
        <LinkTo @route="myprofile" >
            Profile
        </LinkTo>
    </li>
    <li>
        <LinkTo @route="logout" >
            Logout
        </LinkTo>
    </li>
</ul>

However this makes the LinkTo useless as it reloads the page as if following a link instead of transitioning to a new route. We're currently doing this using hember-link-action, but I'd love to find a more idiomatic way to approach this problem.




Data loading issues in Ember 2.17

In ember 2.17 I have the following model :

import DS from 'ember-data';

export default DS.Model.extend({
  sharing_start:DS.attr('date'),
  owner: DS.belongsTo('shop'),
  deleted:DS.attr('boolean'),
  shared:DS.attr('boolean'),
  free_price:DS.attr('boolean'),
  product:DS.belongsTo('product'),
  from_share_products:DS.hasMany('product',{inverse:"shared_from"})
});

I use it in the following model :

import Route from '@ember/routing/route';
import { assign } from '@ember/polyfills';

export default Route.extend({
  model(params){
    return this.get('store').query('shared-product',assign(params,{include:'owner,product'}))
  },
  queryParams: {
    page: {refreshModel: true},
    size: {refreshModel: true},
    scope: {refreshModel: true}
  }
});

The data is rendered in a table, here is the line component used in a each loop :

<td> SP ID :  PRODUCT ID : </td>
<td></td>
<td></td>

If I reload the page on this route It render one line with the product name and ID and the following error :

 "Assertion Failed: You modified \"sp.product\" twice on <marketadmin@model:shared-porduct::ember988:11> in a single render. It was rendered in \"component:shared-products/catalog-line\" and modified in \"component:shared-products/catalog-line\". This was unreliable and slow in Ember 1.x and is no longer supported. See https://github.com/emberjs/ember.js/issues/13948 for more details."

If I go to this route from another route in the app, the array is displayed without console error except that, the first line has no product name or ID, as well as the 8th line (both in FF and chrome), and the following ones have a product name and ID.

The weird part is that in both the refresh or naviguating case, the data is retrieved in one API call that return the data with products as relationship.

I am not sure where to go to diagnose or solve that problem.




Emberjs, inside Controller call this.transitionToRoute('index');

    error: function (jqXHR, exception) {
      console.log('Error occured!');
      this.transitionToRoute('main');
    },

Error: Uncaught TypeError: this.transitionToRoute is not a function