Binding custom UIs to Model


#1

Hi there,

I’m new to Ember. Is there a way to initialize and bind Javascript UI Widgets like Wijmo or KendoUI?

I’ve tried to observe the model and update the Wijmo Flexgrid by hand but didn’t get it to work.

This is what i got so far:

export default Ember.Controller.extend({
  queryParams: ['firstname', 'lastname', 'street', 'zip', 'region', 'city', 'mobile', 'landline'],
  model: {},
  currentPathDidChange: function() {
   Ember.run.schedule('afterRender', this, function() {
      // create the grid and give it some data
      var grid = new wijmo.grid.FlexGrid('#gsFlexGrid');
      this.set('grid', grid);
      //
      return true; // Bubble the didTransition event
    });
  }.observes('currentPath'),
  dependency: function() {
    console.log('the model has changed');
    var grid = this.get('grid'); // this doesn't deliver the grid i want to have!!!
    var entries = [];
    this.get('model').forEach(function (entry){
      entries.push(entry);
    });
    console.log(entries); //some proxy objects and not the main entity!
    grid.itemsSource = entries; //doesn't work!
  }.observes('model')
});

Thanks for the help!
regards


#2

You need to wrap the external component in an Ember.Component.

Assuming you’re using 1.13+

export default Ember.Component.extend({
  willRender() {
    var grid = new wijmo.grid.FlexGrid('#gsFlexGrid');
    this.set('grid', grid);
  }
});

#3

Thanks!

and how can I bind and update the Grid on Ember-Data model changes?


#4

Hm, in that case, the willRender hook is not appropriate as it runs everytime and binding changes. We need to modify it.

export default Ember.Component.extend({
  didInsertElement() {
    var grid = new wijmo.grid.FlexGrid(this.get('element')); // Ember.Component already have an element you can use
    this.set('grid', grid);
  },
  didRender() { // runs every time an attribute changes
    var grid = this.get('grid');
    // do things with grid
  }
});

#5

Sorry, but I’m to stupid to get this!

now I habe my component which I’m passing in the model. But how can i get the Model data as an Array?

{{#wijmo-grid gridData=model}}{{/wijmo-grid}}

export default Ember.Component.extend({
  gridData: [],
  didInsertElement() {
    var grid = new wijmo.grid.FlexGrid(this.get('element')); // Ember.Component already have an element you can use
    this.set('grid', grid);
  },
  didRender() { // runs every time an attribute changes
    var grid = this.get('grid');
    console.log(this.get('gridData'));
    grid.itemsSource = this.get('gridData'); //how can i get the Model data as an Array?
  }
});

#6

What do you mean by getting the model data as an array? What is it exactly? You can get any Ember Object’s class name by converting it to a string, like this console.log(String(obj))


#7

Data for the Wijmo FlexGrid has to be in this form: [{col1:data1, col2:data2},{col1:data3, col2:data4}].

So if i pass in the model with {{#wijmo-grid gridData=model}} I’ve got the whole model in the component. So i need to extract the data out of the model somehow.

I need something like {{#each model as |post|}} only in Javascript


#8

That is correct. You can create a Ember.ComputedProperty on the component that watches change on model. If appropriate, you can even use Ember.computed.map to map over the model with something different.


#9

Thanks to lightblade, here is my final solution so other noobs like me can use JavaScript UI Libraries:

The Component:

import Ember from 'ember';

export default Ember.Component.extend({
  gridData: [],
  entries: Ember.computed.map('gridData', function(data, index){
    var entry = {
      Firstname: data.get('firstname'),
      Lastname: data.get('lastname'),
      Telephone: data.get('telephone'),
      Street: data.get('street'),
      Zip: data.get('zip'),
      Region: data.get('region'),
      City: data.get('city'),
      Mobile: data.get('mobile'),
      Landline: data.get('landline'),
    };
    return entry;
  }),
  didInsertElement() {
    var grid = new wijmo.grid.FlexGrid(this.get('element')); // Ember.Component already have an element you can use
    grid.initialize({
      autoGenerateColumns: false,
      columns: [
        { header: 'Firstname', binding: 'Firstname' },
        { header: 'Lastname', binding: 'Lastname' },
        { header: 'Telephone', binding: 'Telephone' },
        { header: 'Street', binding: 'Street' },
        { header: 'Zip', binding: 'Zip' },
        { header: 'Region', binding: 'Region' },
        { header: 'City', binding: 'City' },
        { header: 'Mobile', binding: 'Mobile' },
        { header: 'Landline', binding: 'Landline' }
      ],
      itemsSource: this.get('entries')
    });

    this.set('grid', grid);
  },
  didRender() { // runs every time an attribute changes
    var grid = this.get('grid');
    grid.itemsSource = this.get('entries');
  }
});

Usage in Template:

{{#wijmo-grid gridData=model}}{{/wijmo-grid}}