Quantcast
Channel: Ember.JS - Latest topics
Viewing all 4838 articles
Browse latest View live

Debugging tips and tricks

$
0
0

@rondale_sc wrote:

I’ve learned many tips and tricks from the Ember.js Community slack that have been lost to other users over the years. I know firsthand how valuable knowing the right trick here or there is to unblocking your problem. So let’s hear them!

Criteria and Guidelines:

  1. It should be generic, though posting specifics to QUnit or Mocha seem fine.
  2. It should be small and understandable.
  3. It should provide sufficient detail to help others use and implement it.

Even small things can help people, so don’t think you can’t share because it is “too basic” or “everybody knows that,” because someone out there might not and this could help them.

And a little bit of attribution goes a long way. If you found this out from someone in the Slack channel, give them a shout out.

You’re experience is valuable, so please feel free to share! :smile:

I think it fair that I start.


Get Settled State

Ember’s test harness wants to wait for async behavior to be completed before it advances the test. It does so by returning a wait promise from many of the test helpers (e.g. visit). The wait function is covered very well in this blogpost. To simplify the wait helper returns a promise that resolves when the following things have completed:

  • router transition
  • scheduled run loops
  • waiters
  • jQuery.ajax

And there is a neat way to kinda “cheat” to figure that out.

Take for instance you have a visit('/some-route'), which does return a wait promise, and you debugger; immediately afterward. You can call the following to get easy access to the state of the wait:

require('@ember/test-helpers').getSettledState()

Which will output something that looks like this:

Pretty excellent. You can use that information to narrow down where you should look if, for instance, your test was timing out.

Shout out to @TBieniek for showing me this in the #-testing channel this afternoon. And inspiring me to create this thread.

Happy (bug) hunting!

Posts: 2

Participants: 1

Read full topic


How to add and save additional row values from a template

$
0
0

@belgoros wrote:

I display 7 rows corresponding to 7 week days: Monday through Sunday with working hours for every day (see the attached screenshot). Some day can have split hours (with time break) when selecting Divided state in the select drop-down. In this case I display additional 2 input fields to enter the times. Here is the template code:

#templates/components/weekday-row.hbs

<div class="form-group row">
  <label for="state" class="col-sm-2 col-form-label">{{translatedWeekDay}}</label>
  <div class="col-sm-2">
    <select class="form-control" onchange={{action "selectState" value="target.value"}}>
      {{#each states as |state|}}
        <option value={{state.id}} selected={{eq state.id weekday.state}}>{{state.name}}</option>
      {{/each}}
    </select>
  </div>
  <div class="col-sm-2">
    {{input type="time"
      class="form-control"
      required=true
      min="06:00"
      max="22:00"
      disabled=isClosed
      pattern="[0-9]{2}:[0-9]{2}"
      value=weekday.opens
    }}
  </div>
  <label for="closes" class="col-form-label">{{t 'working.hours.labels.to'}}</label>
  <div class="col-sm-2">
    {{input type="time"
      class="form-control"
      required=true
      min="06:00"
      max="22:00"
      disabled=isClosed
      pattern="[0-9]{2}:[0-9]{2}"
      value=weekday.closes
    }}
  </div>
</div>
{{#if isDivided}}
  <div class="form-group row">
    <div class="col-sm-2 offset-sm-2">{{t 'working.hours.labels.and'}}</div>
    <div class="col-sm-2">
      {{input type="time"
        class="form-control"
        required=true
        min="06:00"
        max="22:00"
        disabled=isClosed
        pattern="[0-9]{2}:[0-9]{2}"
        value=weekday.opens
      }}
    </div>
    <label for="closes"class="col-form-label">{{t 'working.hours.labels.to'}}</label>
    <div class="col-sm-2">
      {{input type="time"
        class="form-control"
        required=true
        min="06:00"
        max="22:00"
        disabled=isClosed
        pattern="[0-9]{2}:[0-9]{2}"
        value=weekday.closes
      }}
    </div>
  </div>
{{/if}}

Every weekday corresponds to working-hour model item I get in the routersmodel` hook. The problem I can’t figure out how to solve is that when I enter a value in one of the time inputs for Divided status is auto-copied in the same field and I can’t just enter 9 -12 and 14 - 20 hours.

How to do that: separate the binding values ? Should I create a separate model (to trace divided status values) or another solution?

Posts: 1

Participants: 1

Read full topic

Supporting large collections in ember-data

$
0
0

@onsmith wrote:

While developing ambitious web applications with ember, I’ve found that they often naturally result in databases with large collections of records (> 10,000). Obviously, it’s impractical to transmit and load all of these records to the client, which means ambitious web apps almost always need a solution for handling collections that are impossible to fully resolve into a complete list of records.

Here’s the problem: ember-data doesn’t really address this issue, especially when it comes to hasMany relationships. In fact, ember-data tries to fully resolve a hasMany as soon as it is accessed with get, and then once the promise resolves, ember-data assumes that it has all the related records. This behavior can be clunky and does not work for large collections that cannot be resolved. To avoid this behavior, I’ve had to avoid hasMany completely and hack together my own class for dealing with large relationships/collections and preventing ember-data from trying to resolve them automatically.

I can definitely understand ember-data’s approach here, to defer this problem to the developer (while providing methods like query, getReference, and peekRecord to make ambitious developers’ lives easier). Large record collection management requires pagination, filtering, and sorting to work properly, and all three of these techniques are often implemented slightly differently depending on the back-end API.

Nonetheless, JSON API does have recommendations for how to handle pagination, filtering, and sorting, and it would be great if ember-data catered to this recommended structure, at least.

In short, I think ember-data is missing a good solution for managing large record collections. When I encounter a large record collection in the wild, I avoid ember-data’s built-in collection management completely in order to prevent ember-data from trying to load all the records or getting confused when it can’t fully resolve them. A good solution should support JSON API’s recommendation for pagination, filtering, and sorting; it should never try to fully resolve the collection; and it should maintain record parity with ember-data’s store.

If there’s legitimate interest in this, I can try to sketch out an interface for a class that handles large collections and share some of my old attempts at hacking together a solution.

Posts: 1

Participants: 1

Read full topic

How to access nested object properties in 3.0+?

$
0
0

@patrickng wrote:

We are in the process of trying to upgrade our Ember application from 2.15.3 -> 3.1 and am running into a major problem.

Given that we have a simple typeahead that makes an AJAX call to get a list of recipients, we set that to a property with this.set(‘recipientList’, Ember.Object.create(response)). The response looks something like this:

“recipients”: { “total”: 1, “per_page”: 3, “current_page”: 1, “last_page”: 1, “next_page_url”: null, “prev_page_url”: null, “from”: 1, “to”: 1, “data”: [{ “user_id”: 1234, “user_type”: 10, “name”: “Some recipient” }] } }

We later pass this into a nested component as a property: {{dropdownList items=recipientList}}

Inside that component, in 2.15.3 we were able to access the array “data” by doing this.get(‘items.recipients.data’). Now, with the same exact code in 3.0 and 3.1, this.get(‘items.recipients.data’) comes back as undefined. this.get(‘items.recipients’) is also undefined. I can log out this.get(‘items’) and see the recipients object but I can’t seem to access it anymore.

I see there are ES5 getter/setter changes in the release notes but I still can’t figure out how to get this to work. Any tips?

Edit: I will try to provide a link that can reproduce this issue tonight.

Posts: 3

Participants: 2

Read full topic

How to avoid "TaskInstance XXX was canceled..." errors?

$
0
0

@piotrpalek wrote:

Hey, I’m using ember-concurrency and I’m getting this error: TaskInstance XXX was canceled because it belongs to a XYZ Task that was .perform()ed again".

I’ve noticed that’s because I’ve used an ember concurrency task as a promise (task.then(...)) but I didn’t have a catch handler defined. Once I’ve added it (which wasn’t that obvious to me, I think this could be a good thing to add to the docs) the cancellation error was handled, but I’ve noticed that the error object in the catch handler I’m getting is just a string (same as shown in the console).

So now my last issue is, how do I distinguish between cancellation errors, and possible other errors in the catch handler? Imo it’d be great if I could import { cancellationError } from 'ember-concurrency' and use that to ignore the cancellation error and throw if some other issue occured.

edit: derp… ok I have now noticed that it’s not a string, and you can actually call e.name which gets you TaskCancellation, I’ll leave this up, maybe it’ll help someone in the future :sweat_smile:

edit2: Aaaand there’s an taskInstance on the error object which has a isCanceled CP, rubber duck driven development ftw :slight_smile:

Posts: 1

Participants: 1

Read full topic

You probably don't need to wrap in Ember.Object

$
0
0

@ef4 wrote:

I have seen several posts lately where people share code that does things like:

this.set(‘recipientList’, Ember.Object.create(response)).

And rather than hijack those threads, I’m starting a new one to point out: you almost certainly don’t need that Ember.Object.create.

Ember works fine with Plain Old Javascript Objects (POJOs). If you already have a POJO, you can just use the POJO.

The only rule you need to follow to make sure Ember can keep track of your data changing is that you use set to change it. For example, this template:

The value is {{pojo.outside.inside.value}}

Will always render fine and stay up to date even if you implement the component like this:

import { set } from '@ember/object';
import Component from '@ember/component';
export default Component.extend({
  init() {
    this._super();
    this.set('pojo', { outside: { inside: { value: 'a' } } });
  },
  actions: {
     changeIt() {
        set(this.pojo.outside.inside, 'value', 'b');
     }
  }
});

When should you wrap in Ember.Object? Only when you actually want to extend Ember.Object to use a feature like computed properties. If you aren’t extending and you’re just calling Ember.Object.create(...), you almost certainly don’t need to.

Posts: 1

Participants: 1

Read full topic

How to do nested routing

$
0
0

@akhil_ck wrote:

landing --> study --> mapping how can i create route for this can i just create mapping route and specify the path like as ‘landing/study/mapping’ like this

Posts: 1

Participants: 1

Read full topic

Remove a particular file/folder from the app tree depends upon the build environment

$
0
0

@gokulk138 wrote:

I’m trying to remove a folder (app/utils/dev) from the app folder during the production build. I tried using broccoli-file-remover to remove the folder from app tree. But it’s not working for some reason :frowning:

appTree = removeFile(appTree, {
   path: 'app/utils/dev'
});

I think app tree will not maintain the app’s folder structure. But, I’m not sure.

Any suggestions?

Posts: 1

Participants: 1

Read full topic


Glimmer "transaction is null"

$
0
0

@ahopkins wrote:

I’m trying to upgrade an app that was running version 2.5 to Ember 3. I got what I thought was everything cleaned up so that I could finally build the package okay.

The problem is, I am now getting a transaction is null error in my console.

To be honest, I have no clue were to even go to look for this.

Sorry for such a vague question, but I am simply not even sure where to start.

Posts: 2

Participants: 1

Read full topic

Ember build --environment production

$
0
0

@vincenthure wrote:

Hello,

ember build : when I do this everything is ok

ember build --environment production : when I do this is lost all my pictures on my pages!!

I don’t understand how to solve this because in the second case I see that all my icons in the assets folder has changed name and the navigator can’t connect to them.

Vincent

Posts: 1

Participants: 1

Read full topic

Nested routing . there is no router (error)

$
0
0

@akhil_ck wrote:

message : “Assertion Failed: You attempted to define a {{link-to "/landing/study/study-master-mapping"}} but did not pass the parameters required for generating its dynamic segments. There is no route named /landing/study/study-master-mapping”

this.route(‘landing’, function() { this.route(‘study’, function() { this.route(‘mapping’); this.route(‘study-master-mapping’); }); });

link — > {{#link-to “/landing/study/study-master-mapping”}}About{{/link-to}}

Posts: 1

Participants: 1

Read full topic

Ember cp-validations - belongsTo validation

$
0
0

@belgoros wrote:

I didn’t find the answer in the examples provided in ember-cp-validation dummy app as well in their presentation.

I have to validate a language in the following model:

# models/shop-language.js

import DS from 'ember-data';
import { validator, buildValidations } from 'ember-cp-validations';

const Validations = buildValidations({
  language: {
    description: 'Language',
    validators: [validator('ds-error'), validator('presence', true)]
  },

  shop: {
    description: 'Shop',
    validators: [validator('ds-error'), validator('presence', true)]
  },
});

export default DS.Model.extend(Validations, {
  shop: DS.belongsTo('shop', { async: true }),
  language: DS.belongsTo('language', { async: true }),
  modifiedBy:  DS.attr('string')
});

On which property should I use v-getin the template if I load 2 models from my route:

#routes/shop-languages.js

model() {
    return RSVP.hash({
      shopLanguages: this.store.query('shop-language', { shop_id: this.get('currentShop.shop').get('id')}),
      languages: this.store.findAll('language')
    });
  },

Here is the template:

#templates/shop-languages.hbs
...
{{#each model.shopLanguages as |shopLang|}}
        <li class="list-group-item">
          {{shopLang.language.tag}}
          <button type="button" class="btn btn-danger btn-sm" disabled={{isDeleteButtonDisabled}} {{action "deleteLanguage" shopLang}}>
            <span class="oi oi-trash"></span>
          </button>
        </li>
      {{/each}}

  <form {{action "saveLanguage" aLanguage on="submit"}} class="form-inline">

          {{#if showLanguageError}}
            <div class="alert alert-danger">
              {{v-get aLanguage 'id' 'message'}}
            </div>
          {{/if}}

          <div class="col-sm-2">
            {{#power-select
              class="form-control"
              placeholder=placeholderText
              selected=aLanguage
              options=model.languages
              searchField="tag"
              noMatchesMessage=(t 'components.language.labels.not.found')
              onchange=(action (mut aLanguage))
              focus-out=(action (mut showLanguageError) true)
              as |language|
            }}
            {{language.tag}}
            {{/power-select}}
          </div>

<div class="form-check sm-2">
            <button type="button" type="submit" class="btn btn-success btn-sm">
              <span class="oi oi-plus"></span>
              {{t 'buttons.add'}}
            </button
...

Here is how I tried to save a newly added language in the route:

# routes/shop-languages.js

actions: {
...
  async saveLanguage(aLanguage) {
   ...
  try {
        await shopLanguage.save();
        controller.set('aLanguage', '');
        route.get('flashMessages').success(route.get('i18n').t('flash.language.added'));
        route.refresh();
      } catch(response) {
        let error = response.errors[0];
        console.log('+++++ in CATCH block error: ' + error);
        if (error.status !== "422") {
          throw response;
        }
      }

It prints the error to the console but displays nothing in the template … :frowning: The response I get from Rails backend if language is not selected:

{"message":"Couldn't find Language"}

Should parse in some way this message to be able to display it ? And the error object is as follows:

{status: "404", title: "The backend responded with an error", detail: "[object Object]"}

Thank you.

Posts: 1

Participants: 1

Read full topic

Replace mirage with real database

$
0
0

@ondrejsevcik wrote:

Hi, I would like to replace mirage with a real database connection. The problem is setting up test data. I don’t want to create them upfront in the database, because it’s very fragile and tends to get obsolete very fast. I would like to keep all my test data within the test.

I had an idea that I would call a CLI command before every test to reset the database and populate it with test data from the test. Is something like that possible using ember-cli?

I know that the tests run inside the browser which obviously can’t call any CLI command but during the compilation step, it should be possible to run some CLI commands as it runs inside the node, right?

Posts: 1

Participants: 1

Read full topic

Actions now use run.join not run

$
0
0

@rondale_sc wrote:

Mostly documenting this for future travelers…here goes.

So in this commit:

The internal ember-glimmer package changed from using Ember.run to using Ember.run.join. If you aren’t familiar with the difference the former creates a nested “runloop” and the latter will either join an existing “runloop” or if one is not available will create one.

99% of the time when people use Ember.run they could be better served by using Ember.run.join. This is because when you call Ember.run you ALWAYS nest a whole runloop which carries with it a lot of unnecessary book keeping and work.

When I updated my project from 3.1 to 3.2 this change broke 9 tests. Just to be clear; each of these tests were incorrectly written. But the general gist was something like this (pay specific note the when you click .find-by-something it triggers a closure action):

this.render(hbs`
  {{something}}
`);

await $('.find-by-something').click();

assert.ok(/* something happens here as a result of a call to an action */);

The solution is to rewrite like this:

this.render(hbs`
  {{something}}
`);

$('.find-by-something').click();

await settled().then(function() {
  assert.ok(/* something happens here as a result of a call to an action */);
});

First of all, the first example likely never should have worked. But let’s talk about what is happening.

When you await a jQuery click you aren’t really doing anything that Ember knows or cares about because $(...).click() doesn’t return a promise. So don’t think too hard about that line.

It does however trigger a runloop, since Ember wraps events in a runloop to handle side effects, and to be generally helpful. Previously, before the commit linked above, this would create a runloop and then the action would trigger which would create a nested runloop.

The nested runloop would completely flush before the outer or parent runloop (instantiated by Ember’s click handler). Which means you’d end up with a guarantee that Ember’s action and all of it’s associated side effects would be handled before the click runloop (the outermost runloop) finished. Which sorta simulates synchronous behavior.

This is BAD. Because it means that we are blocking rendering while those actions fire.

So the commit fixes this by scheduling the action into the current runloop with join.

A simplified example of the difference:

This really would have been a lot easier with the new test helpers. Since helpers will handle the settling of runloops out of the box. See more details here about that: https://guides.emberjs.com/v3.1.0/testing/testing-components/

Thanks to @rwjblue and @kpfefferle for helping me talk through what was happening in these cases.

Posts: 1

Participants: 1

Read full topic

Datadown to a component leads to memory leak?

$
0
0

@Srinithi wrote:

Hi… I have a simple ember app that does data-down to a component

I basically want to avoid memory leaks in my app. I tested in canary and found that there are detached HTMLDivElements… Below is the screenshot… Are these really memory leaks? If yes, Can someone please help me out on how to avoid these leaks? Also, is there anyway to find the source of the leaks from the heap snapshots?

Here is the twiddle

https://ember-twiddle.com/8e3cf314c7885ec42c06ed3fab236020?openFiles=templates.components.memory-leak-parent.hbs%2Ctemplates.components.memory-leak-child.hbs

I did the following:

  1. Took a heap snapshot after loading the twiddle (snapshot1)
  2. Clicked on Show/Hide child button to show the child component
  3. Clicked on Show/Hide child button to hide the child component
  4. Took a heap snapshot ( snapshot 2 ) Compared the snapshots and found the following

Posts: 1

Participants: 1

Read full topic


Testing Engines with ember-qunit >= 3.4

$
0
0

@lennyburdette wrote:

When testing an Ember Engine, we want to run acceptance tests with the dummy app, but unit and integration tests with the engine itself. We found a solution, and I wanted to share it for others and to see if there’s a better way.

We want most tests to use the engine’s resolve so that this.lookup('component:my-button') finds the engine’s component (from the addon/ directory):

// tests/test-helper.js
import { start } from 'ember-qunit';
import { setResolver } from 'ember-test-helpers';
import engineResolverFor from 'ember-engines/test-support/engine-resolver-for';
 
setResolver(engineResolverFor('my-engine-name'));
 
start();

But for acceptance tests, we want to set up the dummy application so that we have a full application to run, like so:

import { module, test } from 'qunit';
import { setupApplicationTest } from 'ember-qunit';
import { visit, currentURL } from '@ember/test-helpers';

module('basic acceptance test', function(hooks) {
  setupApplicationTest(hooks);

  test('can visit /', async function(assert) {
    await visit('/');
    assert.equal(currentURL(), '/');
  });
});

Because we never called setApplication (as described in the ember-qunit readme), this will fail. But once we call setApplication, it will override the setResolver call and all unit and integration tests will fail. So we came up with a custom “setup” function that uses setupApplicationTest under the hood:

// tests/helpers/dummy.js
import Application from '../../app';
import config from '../../config/environment';
import { setApplication } from '@ember/test-helpers';
import { setupApplicationTest } from 'ember-qunit';
 
export function setupDummyApplicationTest({ beforeEach, afterEach }, options) {
  const hooks = {
    beforeEach(fn) {
      return beforeEach(function(...args) {
        setApplication(Application.create(config.APP));
        return fn.apply(this, args);
      });
    },
 
    afterEach(fn) {
      return afterEach(function(...args) {
        setApplication(null);
        return fn.apply(this, args);
      });
    }
  };
 
  setupApplicationTest(hooks, options);
}

So we can fix the above example by swapping setupApplicationTest with setupDummyApplicationTest. And calling setApplication(null) in afterEach() allows the next test to use the engine’s resolver as specified in tests/test-helper.js.

Are there are any downsides to this approach? Or: is there a better pattern we should be using?

Posts: 1

Participants: 1

Read full topic

Ember In Repo Engines

$
0
0

@JKP wrote:

Is there any way to group in-repo engines under a folder. Let’s say, i have 4 in-repo-engines namely A, B, C1 and C2. I want to group C1 and C2 in-repo-engines under a folder called C (Folders - lib>> C>> C1 , lib>> C>> C2). Is this possible? If so, what are the other configurations we must do?

Posts: 1

Participants: 1

Read full topic

Promise rejected before it renders: _emberCliMirage.default.initialize is not a function

$
0
0

@mungalmaroti wrote:

Hi Friends,

I am stuck how to set Promise in integration test case with ember js .

Please let us me.

Regards, Maroti

Posts: 2

Participants: 1

Read full topic

Observe through reference API?

$
0
0

@ef4 wrote:

I know I can use the reference API to synchronously read what type and id a belongsTo relationship is pointing at.

But if I want to use those in a computed property, and I want the property to invalidate correctly, what should I observe?

(And does the answer change if the relationship is sync vs async?)

Posts: 1

Participants: 1

Read full topic

Ensuring treeForApp from Addon1 runs before Addon2

$
0
0

@samselikoff wrote:

I’m working on AddonDocs, and it depends on Mirage. I want the treeForApp hook from AddonDocs to run before the treeForApp hook from Mirage (so that AddonDocs can create a file that Mirage expects, in case the host app doesn’t provide it).

In AddonDocs’ package.json I made sure to specify that it should run before Mirage:

"ember-addon": {
  "configPath": "tests/dummy/config",
  "before": [
    "ember-cli-mirage",
    "ember-cli-htmlbars",
    "ember-svg-jar"
  ],
  "after": [
    "ember-modal-dialog"
  ]
}

and defined treeForApp

treeForApp(app) {
  console.log('here in addon docs..');

  // snip
}

I also cracked open node_modules/ember-cli-mirage/index.js and added a log to Mirage’s hook:

treeForApp(appTree) {
  console.log('here in mirage');
  
  // snip
}

Here’s the output from terminal:

➜  ember-cli-addon-docs git:(fix-mirage) ✗ ember s
here in mirage
here in addon docs..
here in mirage

Any ideas what’s going on?

Posts: 1

Participants: 1

Read full topic

Viewing all 4838 articles
Browse latest View live