mardi 30 mars 2021

Ember defineProperty not reflecting on template until notifyProperty change is called?

I basically have a feature flag which gets added into a list on user saving a configuration. On save I create a computed property on a service object as showing below.

  defineFeature(feature) {
    defineProperty(this, `is${classify(feature)}`, computed('session.account.features.[]', 
     function() {
      return this.hasFeature(feature);
    }));
  },

Now this sets the property on the service object and I consume it in my .hbs file. However it does not reflect unless I trigger <serviceObj>.notifyPropertyChange('is<FlagName');

I am confused why Ember doesn't update by itself or am I doing something wrong?

Ember: v3.4




lundi 29 mars 2021

How to make a pdf file from a page in emberjs

Is there a way in emberjs to save the complete look of the website page and download it as a pdf file via button?




samedi 27 mars 2021

How to reload any page on Transition in ember js using transitionTo?

  • I'm deleting a record in the details page (i.e., host/items/details/<id>) using a delete button, the whole page is inside a component .
  • After deleting, I'm redirecting to another route(i.e., host/items/all), which list all the items.
  • But the list in the route (i.e., host/items/all) still contains the deleted record !

I'm think i should refresh the page, but i can neither refresh the model in the ember store nor refresh the page using when using Transition to.

  • this.refresh is only accessible inside a route.js file
  • I can't refresh a page from a component.js file

I'm new to ember, Please some one give me a solution !




vendredi 26 mars 2021

Ember.JS Data Model save() errors with 'options is undefined'

I've got a small snippet of code, where I check for a model existing in the current data store. If it doesn't already exist I create it and save it. This used to work on an older version of ember-cli (3.8), however throws this error as of an upgrade to 3.21.

let myModel = this.store.peekRecord('modelName', this.newModelId);

if (!myModel) {
    myModel = this.store.createRecord('modelName', {
        id: this.newModelId
    });


    await myModel.save({});
}

When executing model.save() it errors out with options is undefined, stepping into the code for save, it shows options being passed as a parameter of save(), however the ember documentation and everywhere else, save is used with no parameters.

Any help as to why this error is being thrown would be very helpful, thank you.




mardi 23 mars 2021

Testing Service Worker Ember Octane

I am using ember-service-worker to implement offline behavior for my app, so far it does what I need, but I am wondering how can I write some test for my app, to test the service worker is doing his job properly and also because this breaks my current integration tests.

in offline mode I use indexeddb to catch the request and then resync the data when the user have a more stable connection.

thanks a lot for your help :D




lundi 22 mars 2021

How to Use jquery datatables in ember js?

How to add jquery inside the ember js file and how to use the jquery data table Can anyone please tel me in a step by step procedure and I’m also new to ember js




Pass multiple args in Ember JS prop

I have a function that lives in a component and I want to pass multiple arguments to it from the parent. I realise I can pass them individually but I'd like to pass them as one arg if possible.

I'd like this to work but the syntax in actionArgs isnt correct

<MyComponent @actionName= @actionArgs= />

<button ></button>

I've tried wrapping in parenthesis but that didnt work either.




How do you have only one menu item open at a time in ember js?

We have a page in ember js which has multiple menus. When you click on an icon the menu should open and when you click on a close button it should close. The only problem is that when you click one and then a second one, they are both open at the same time but what we want is for only one to be open at a time. any suggestions on how to fix this?


 <div> Menu items </div>


showMenu(){
  this.set('showMenu', true);
},
hideMenu(){
  this.set('showMenu', false);
},



Is store.unloadAll on ember data 2.18.x suppose to make an ajax call?

The Context:

I just updated an Ember App from 2.16 to 2.18.

The Situation

In our code, we are manually cleaning up one of our models data by doing: store.unloadAll('myModel'); inside an ember.run, the code looks like this:

Ember.run(function() {
    store.unloadAll('myModel');
});

and I am seeing some ajaxs calls being made to the .../myModel endpoints.

The problem

I cannot explain why those ajax calls are being done.

What I have tried

I am running the store.unloadAll('myModel'); outside of the Ember.run block, and not seeing the issue any longer, however, I really would like to understand why this is happening.




vendredi 19 mars 2021

Ember JS: Access peekAll length in console

I am using the following code in my router in the Model hook.

const listings = this.store.peekAll('listings');
console.log(listings); // returns a class with a length of 6
console.log(listings.length); // return 0

I am trying to find a way to access the length in the console. I have read its not available in the console but I'm sure there must be a way.




nested engines cannot render components

I am trying to create nested engines (with routes) like this:

Host App
    mounts: Engine A
    mounts: Engine B

There are components in both engines. Host app can render components from both engines and everything works fine. However once I add Engine A as dependency of engine B like this:

        mounts: Engine A
        mounts: Engine B
            mounts: Engine A

Component from engine A cannot be rendered in route in engine B: "Attempted to resolve component-a, which was expected to be a component, but nothing was found."

Are nested engines supported or do you have any idea, what might be wrong?

thanks a lot




mercredi 17 mars 2021

How to avoid Ember tests failing if endpoint returns 404?

The Context:

I have an ember app, which I just updated from 2.16 to 2.18.2 (latest from the 2.x versions). I have a stubby server for testing purposes.

The Problem

When running my tests, some endpoints returns an 404 (which is expected), but my test fails with the following log:

not ok 32 Chrome 79.0 - [undefined ms] - Global error: Uncaught Error: Ember Data Request GET http://127.0.0.1:8882/stubby/patito/214 returned a 404
Payload (Empty Content-Type)

What I have tried

I added mock endpoint to return some data. The problem here is adding too many and unnecessary data.

Is there any possible way to flag those 404 as expected since they are not needed for a particular test to pass?




How to use jQuery AJAX in ember v3.2.5?

I tried writing code that gives the alert message inside the function but the success or error block seems doesn’t work.

How can I call the function properly? I'm using the latest Ember version (3.2.5). Here is my AJAX code in the app/controller

import Controller from '@ember/controller';
import $ from 'jquery';
export default Controller.extend({
  actions: {
    validateUser: function() {
      let res = this;
      var userName = this.get('username');
      var userPassword = this.get('password');

      $.ajax({
        type: "POST",
        url: "InsertServlet",
        data: {
          userId: userName,
          password: userPassword
        },
        success: function(data) {
          if (data == 1) {
            alert('valid user');
          } else {
            alert("Invalid User");
          }
        },
        error: function(xhr, status, error) {
          alert(xhr.responseText);
        }
      });
    },
  }
});



dimanche 14 mars 2021

Still receiving 401 unauthorized after including credentials : 'include' in HTTP requests

I am new to Ember.js and I am currently working on a vehicle app. I have done the login part in which I have an HTTP Post request with fetch which has credentials : 'include' in the init object and send it to the server, which is remote. On a successful login the user is transitioned to the home page where there are three option buttons: vehicles, logout and Profile Data. Moreover, cookies are set as the login response has a set-cookie header. At the moment I am not using the vehicles button, but the other two do not work as expected. For them I have made two other http fetch request in which I have credentials : 'include' in the init object but I assume that I cannot access the cookies in which there is my jsessionId. I tried to read them with document.cookie, but it turned out that jsessionId is HTTP only which means that it cannot be accessed through JavaScript.

If I read the cookies, I could include them in my two fetch requests for logout and getUser I think that then the requests would be successful.

Am I right or not and what should I do ? Thanks for the help in advance.

Here are some of my source files:

components/login.js

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

export default class LoginComponent extends Component{
  @tracked email;
  @tracked password;
  @service router;

  @action
  logUser(e){
    e.preventDefault();
    let userData = {
        'email' : this.email,
        'password' : this.password
    };
    let fetchObject = {
        method: 'POST',
        credentials: 'include',
        headers : {
            'Content-type' : 'application/json',
        },
        body : JSON.stringify(userData),
    };
    fetch('https://gara6.bg/auto-api/users/login', fetchObject)
        .then(response =>{
            return response.json();
        })
        .then(data =>{
            if(data.statusCode == 'SUCCESS'){
                this.redirectHome(data);
            }
            else{
                throw Error('Check your data or connection');
            }
        })
        .catch(error =>{
            alert('Unable to log in ! ' + error);
        });
  }

  redirectHome(data){
      this.router.transitionTo('home');
  }

}

components/login.hbs

<form  id='login'>
    <label id="label" class="formElement" for="exampleInputEmail1">Email address</label>
    <Input class="form-control formElement input" id="exampleInputEmail1" placeholder="Enter email" @value=/><br>
     <label id="label" for="exampleInputPassword1">Password</label>
    <Input class="form-control formElement input" id="exampleInputPassword1" placeholder="Password" @value=/><br>
    <button id='loginLink' class='btn btn-primary btn-lg formElement ' type='submit'>Log In</button> 
</form>

templates/home.hbs:

<h1>Welcome User!</h1>
<OptionButtons/>

components/option-buttons.hbs:

<div class="buttonHolder">
    <button  class='btn btn-primary btn-lg homeButton' type='button' >Log Out</button><br>
    <button  class='btn btn-primary btn-lg homeButton' type='button'>Vehicles</button><br>
    <button  class='btn btn-primary btn-lg homeButton' type='button' >Profile Data</button><br> 
</div>

components/option-buttons.js

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

export default class OptionButtonsComponent extends Component {

    @service router;

    @action
    userMe(){
      let fetchObject = {
          method: 'GET',
          headers : {
              'Content-type' : 'application/json',
          },
      };
      fetch('https://gara6.bg/auto-api/users/me', fetchObject)
          .then(response => {
              return response.json();
          })
          .then(data => {
              if(data.statusCode == 'SUCCESS'){
                 console.log(data.data);
              }
              else{
                  throw ('Check your internet connection');
              }
          })
          .catch(error =>{
              alert('Unable to Log out ! '+ error);
          });
    }

    @action
    logOut(){
        let fetchObject = {
            method: 'POST',
            headers : {
                'Content-type' : 'application/json',
            },
        };
        fetch('https://gara6.bg/auto-api/users/logout', fetchObject)
            .then(response => {
                return response.json();
            })
            .then(data => {
                if(data.statusCode == 'SUCCESS'){
                    this.backToLogin();
                }
                else{
                    throw ('Check your internet connection');
                }
            })
            .catch(error =>{
                alert('Unable to Log out ! '+ error);
            });
    }

    backToLogin() {
        this.router.transitionTo('login');
    }
}



vendredi 12 mars 2021

Unable to serialize backend response in ember data

I am trying to access the pagination variables in the response such as page_number, total_pages inside my controller as I have introduced this feature just now to this legacy code in the backend and now I am stuck how can I read those data and go further.

My serializer code

import DS from 'ember-data';


var underscore = Ember.String.underscore;
export default DS.RESTSerializer.extend(DS.EmbeddedRecordsMixin, {
  attrs: {
    rules: {
      embedded: 'always'
    },

    test_cases: {
      serialize: "id",
      deserialize: 'records'
    },
  },
  keyForRelationship: function (rawKey) {
    return underscore(rawKey) + "_id";
  }
})

route.js

import Route from '@ember/routing/route';
import { hash } from 'rsvp'
import ResetScrollMixin from 'admin-frontend/mixins/reset-scroll-mixin'
export default Route.extend(ResetScrollMixin, {

  model(params) {
    return hash({
      ruleSetVersions: this.store.query('rule-set-version', {
        rule_set_id: params.rule_set_id,
        is_archived: false,
        page: '1'
      }),
      ruleSet: this.store.findRecord('rule-set', params.rule_set_id)
    })
  }
});

And response json looks like

{
    "page_number": 1,
    "page_size": 5,
    "rule_set_versions": [{
        "id": 930,
        "last_updated_by": 1,
        "created_by": 1,
        "default_rule_id": 963,
        "is_live": true,
        "is_archived": false,
        "start_time": "2020-12-30T18:30:00Z",
        "rule_set_id": 11,
        "rules": [{
            "id": 963,
            "priority": 10000001,
            "conditions": [],
            "results": [{
                "id": 59,
                "operator": null,
                "value": "00",
                "rule_id": 963,
                "rule_set_metadatum": {
                    "created_at": "2020-11-18T10:01:38Z",
                    "datatype": "integer",
                    "id": 34,
                    "name": "edd_result",
                    "property_category": "result",
                    "updated_at": "2020-11-18T10:01:38Z",
                    "validations": {
                        "max": 99999,
                        "min": 0
                    }
                },
                "created_at": "2020-11-18T10:10:41Z",
                "updated_at": "2020-11-18T10:10:41Z"
            }],
            "created_at": "2020-11-18T10:10:32Z",
            "updated_at": "2020-11-18T10:10:32Z"
        }, {
            "id": 971,
            "priority": 1,
            "conditions": [{
                "id": 57,
                "comparator": "equal_to",
                "value": "100",
                "rule_id": 971,
                "rule_set_metadatum": {
                    "created_at": "2020-11-18T10:01:05Z",
                    "datatype": "text",
                    "id": 33,
                    "name": "edd_con",
                    "property_category": "condition",
                    "updated_at": "2020-11-18T10:01:05Z",
                    "validations": {}
                },
                "created_at": "2020-12-23T09:05:04Z",
                "updated_at": "2020-12-23T09:05:04Z"
            }],
            "results": [{
                "id": 66,
                "operator": null,
                "value": "100",
                "rule_id": 971,
                "rule_set_metadatum": {
                    "created_at": "2020-11-18T10:01:38Z",
                    "datatype": "integer",
                    "id": 34,
                    "name": "edd_result",
                    "property_category": "result",
                    "updated_at": "2020-11-18T10:01:38Z",
                    "validations": {
                        "max": 99999,
                        "min": 0
                    }
                },
                "created_at": "2020-12-23T09:05:10Z",
                "updated_at": "2020-12-23T09:05:10Z"
            }],
            "created_at": "2020-12-23T09:04:54Z",
            "updated_at": "2020-12-23T09:04:54Z"
        }],
        "created_at": "2020-11-18T10:10:32Z",
        "updated_at": "2020-12-23T09:06:04Z"
    }, {
        "id": 932,
        "last_updated_by": 1,
        "created_by": 1,
        "default_rule_id": 969,
        "is_live": true,
        "is_archived": false,
        "start_time": "2020-11-25T18:30:00Z",
        "rule_set_id": 11,
        "rules": [{
            "id": 969,
            "priority": 10000001,
            "conditions": [],
            "results": [{
                "id": 64,
                "operator": null,
                "value": "1000",
                "rule_id": 969,
                "rule_set_metadatum": {
                    "created_at": "2020-11-18T10:01:38Z",
                    "datatype": "integer",
                    "id": 34,
                    "name": "edd_result",
                    "property_category": "result",
                    "updated_at": "2020-11-18T10:01:38Z",
                    "validations": {
                        "max": 99999,
                        "min": 0
                    }
                },
                "created_at": "2020-11-25T11:53:58Z",
                "updated_at": "2020-11-25T11:53:58Z"
            }],
            "created_at": "2020-11-25T11:53:49Z",
            "updated_at": "2020-11-25T11:53:49Z"
        }, {
            "id": 970,
            "priority": 1,
            "conditions": [{
                "id": 56,
                "comparator": "equal_to",
                "value": "100",
                "rule_id": 970,
                "rule_set_metadatum": {
                    "created_at": "2020-11-18T10:01:05Z",
                    "datatype": "text",
                    "id": 33,
                    "name": "edd_con",
                    "property_category": "condition",
                    "updated_at": "2020-11-18T10:01:05Z",
                    "validations": {}
                },
                "created_at": "2020-11-25T11:54:11Z",
                "updated_at": "2020-11-25T11:54:11Z"
            }],
            "results": [{
                "id": 65,
                "operator": null,
                "value": "100",
                "rule_id": 970,
                "rule_set_metadatum": {
                    "created_at": "2020-11-18T10:01:38Z",
                    "datatype": "integer",
                    "id": 34,
                    "name": "edd_result",
                    "property_category": "result",
                    "updated_at": "2020-11-18T10:01:38Z",
                    "validations": {
                        "max": 99999,
                        "min": 0
                    }
                },
                "created_at": "2020-11-25T11:54:16Z",
                "updated_at": "2020-11-25T11:54:16Z"
            }],
            "created_at": "2020-11-25T11:54:03Z",
            "updated_at": "2020-11-25T11:54:03Z"
        }],
        "created_at": "2020-11-25T11:53:49Z",
        "updated_at": "2020-11-25T11:55:12Z"
    }, {
        "id": 934,
        "last_updated_by": 1,
        "created_by": 1,
        "default_rule_id": 974,
        "is_live": false,
        "is_archived": false,
        "start_time": "2020-12-30T18:30:00Z",
        "rule_set_id": 11,
        "rules": [{
            "id": 974,
            "priority": 10000001,
            "conditions": [],
            "results": [{
                "id": 69,
                "operator": null,
                "value": "00",
                "rule_id": 974,
                "rule_set_metadatum": {
                    "created_at": "2020-11-18T10:01:38Z",
                    "datatype": "integer",
                    "id": 34,
                    "name": "edd_result",
                    "property_category": "result",
                    "updated_at": "2020-11-18T10:01:38Z",
                    "validations": {
                        "max": 99999,
                        "min": 0
                    }
                },
                "created_at": "2021-03-11T10:55:44Z",
                "updated_at": "2021-03-11T10:55:44Z"
            }],
            "created_at": "2021-03-11T10:55:44Z",
            "updated_at": "2021-03-11T10:55:44Z"
        }, {
            "id": 976,
            "priority": 1,
            "conditions": [{
                "id": 60,
                "comparator": "equal_to",
                "value": "100",
                "rule_id": 976,
                "rule_set_metadatum": {
                    "created_at": "2020-11-18T10:01:05Z",
                    "datatype": "text",
                    "id": 33,
                    "name": "edd_con",
                    "property_category": "condition",
                    "updated_at": "2020-11-18T10:01:05Z",
                    "validations": {}
                },
                "created_at": "2021-03-12T16:18:04Z",
                "updated_at": "2021-03-12T16:18:04Z"
            }],
            "results": [{
                "id": 71,
                "operator": null,
                "value": "100",
                "rule_id": 976,
                "rule_set_metadatum": {
                    "created_at": "2020-11-18T10:01:38Z",
                    "datatype": "integer",
                    "id": 34,
                    "name": "edd_result",
                    "property_category": "result",
                    "updated_at": "2020-11-18T10:01:38Z",
                    "validations": {
                        "max": 99999,
                        "min": 0
                    }
                },
                "created_at": "2021-03-12T16:18:10Z",
                "updated_at": "2021-03-12T16:18:10Z"
            }],
            "created_at": "2021-03-12T16:17:55Z",
            "updated_at": "2021-03-12T16:17:55Z"
        }],
        "created_at": "2021-03-11T10:55:44Z",
        "updated_at": "2021-03-11T10:55:44Z"
    }],
    "total_entries": 3,
    "total_pages": 1
}

I am able to read and parse all the data inside the rule_set_versions array but I am unable to access the pagination params that are out side it.

Ember noob here.




Can not open exported excel file in ExcelJS

I have used ExcelJS libary in my JS project. It works fine with English letters. But if I change my application language in to French and export the content as a excel sheet. Then the below mentioned error is coming. Anyone know what cause this issue and a solution for this?

enter image description here




mardi 9 mars 2021

Cannot set img width/height in SetDragImage()

I was trying to customize drag image. What I did was

dragStart(event) {
    event.dataTransfer.setData('type', event.target.getAttribute('data-type'));
    event.dataTransfer.setData('id', event.target.id);

    let img = document.createElement('img');
    img.setAttribute('src', event.target.src);
    img.style.width = '50px';
    img.style.height = '50px';
    event.dataTransfer.setDragImage(img, 0, 0);
  } 

I tried various ways but the drag image is still the same size as my src. Screenshot

Thanks.




dimanche 7 mars 2021

Uncaught type error: Cannot read property 'ajax' of undefined

I'm new to ember.js and this is my first application. I want to build a login form in which if the user has passed in the right email and password, he should be transitioned to the home page. I am not sure whether I should use Ember Data for the login part but I read somewhere that Ember Data is not suitable for this specific login task so I should make ajax request (Is this assumption right ?). However, when I made the request I received the following error :

Uncaught type error: Cannot read property 'ajax' of undefined at LoginComponent.logUser

I have made the http request in a login component class but I am not sure whether I should use a controller for this part as in all the examples I have seen the request was handled in controllers. However, I do not know how to use the login controller on a click on the login button.

So I have a few more questions apart from how to handle the error that I have:

  1. Should I use Ember Data (if yes how) for the login task or should I use the ajax method?
  2. What is the difference between a controller and component(the class) and when I should use each of them user clicks on handling data or making request as in this case?

Thank you in advance for your help!

Here is my code

login.hbs - template:

<h1 id="pageTitle">Log In</h1>
<Login/>

login.hbs - component:

<form  id="login">
    <label class='formElement labelLogin'>Email :</label><br>
    <Input class='formElement input' @value=/><br>
    <label class='formElement labelLogin'>Password :</label><br>
    <Input class='formElement input' @value=/><br>
    <button id="loginButton" class='button formElement' type="submit">Log In</button> 
</form>

login.js - component class

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

export default class LoginComponent extends Component{
  @tracked email;
  @tracked password;

  @action
  logUser(){
        let userData = JSON.stringify({
            'email' : this.email,
            'password' : this.password
        });
        Ember.$.ajax({
            url : 'https://gara6.bg/auto-api/users/login',
            type : 'POST',
            dataType: 'json',
            data : userData,
        }).then(() => {
            alert('Logged In');
            this.transitionToRoute('home');
        }).catch(function(error){
            alert(`Error: ${error}`);
        });
    }
}

routes.js:

import EmberRouter from '@ember/routing/router';
import config from 'gara6/config/environment';

export default class Router extends EmberRouter {
  location = config.locationType;
  rootURL = config.rootURL;
}

Router.map(function () {
  this.route('login');
  this.route('home');
});
  



Autogenerate import for Ember

Im using Ember with VS Code.

What I need is to generate import string on a fly when I encounter dependency. For example I write someting like:

@tracked isLarge = false;

But I don’t have “@tracked” imported yet. So the otion could be to set the coursor on @tracked, press something like “Action + .” and pick “generate import”. It should generate import string:

import { tracked } from '@ember/tracking';

But it doesn’t work out of the box. How can I do that?




samedi 6 mars 2021

Ember - Pass Event and Other Parameter to Action Handler

In my Ember component, I have a list of strings, and a function that update the string at certain index of the list.

animals: computed(function() {
    return ["dog", "cat"];
}),

updateAnimal(value, index) {
    this.animals[index] = value;
},

In my hbs, I render the list of strings into text fields, within a #each loop. When I focus-out the text field, I want to update the string at the certain index.


    <textarea
        value=
        
    />

But how can I pass in the index to the handler as well? In other words, how can I pass the event and some extra parameter at the same time? Thanks a lot for answering my question!!




lundi 1 mars 2021

ember willTransition is called in parent route even after the transition is aborted using transition.abort in child route

Can we prevent calling parent's willTransition() hook if we abort the transition in child route's willTransition() hook using transition.abort()? I can't find correct documentation in Ember official blog.




How to reload hasMany relationship in ember-data with ember octane?

After upgrading to Ember 3.21.2 from 3.9, reloading hasMany relationships is not working properly anymore. For example the following model hook to fetch editable contents for a user does not update the user model anymore.

model(params) {
    const { user } = this.modelFor('application')

    const requestParams = this.mapParams(params)

    return RSVP.hash({
      user,
      results: user.hasMany('editableContents').reload({
        adapterOptions: requestParams
      })
    })
  },

It still triggers requests, but it loads the same contents with every request, even after the request params have changed. Initially the request is sent to /users/:user_id/editable-contents?filter=......

After changing the adapter options it sends a request for each content to /contents/:content_id

We believe the .reload() function is to blame. Is there a new best practice for updating the editableContents relationship on the user model that came with Octane?

We are using:

"ember-cli": "~3.21.2",
"ember-data": "~3.21.0"

Any help is appreciated. Thanks!