Ember.js QT w/ Javascript Bridge - c++

We have a full desktop application based in QT C++ (mac & windows). We utilize webkit to serve up the UI based in HTML and Javascript. We also interact with the C++ via a javascript bridge. I'm doing quite the overhall and incorporating Ember.js as the MVC for a much more modular UI.
My question pertains to the best method for persistance. Should I stick with the Javascript objects we currently utilize, or transition to Ember Data for persistence, and read/write via a function in Ember Data(translation layer)?
Also we utilize webkit, but should I see about instead utilising Node.js rather than strait html/js?
I'd like to not do drastic changes, but I want to do this right. Any advice?

From the Ember side, there's no reason to use Ember Data, because Ember works fine without it. But Ember's infrastructure relies heavily on the API provided by Ember.Observable, which is available to all subclasses of Ember.Object. Similarly, JavaScript arrays will support more Ember features if you use Ember.Array and Ember.MutableArray, although this will happen automatically unless you disable Ember.EXTEND_PROTOTYPES.
So one very reasonable approach would be to port your existing model classes to Ember.Object. That would require, among other things, using get and set to access properties. If you do this, then your objects will be first class Ember citizens, and you'll have access to all the neat features of Ember, including automatic view updates and data bindings.
Here's what Ember.Object looks like, and how it integrates with the rest of Ember:
MyApp.Person = Ember.Object.extend({
firstName: null,
lastName: null,
init: function () {
// You can put more initialization code here.
},
// Compute fullName based on firstName and lastName.
// This will automatically propagate updates when
// firstName or lastName changes.
fullName: function () {
return this.get("firstName") + " " + this.get("lastName");
}.property("firstName", "lastName")
});
var person = MyApp.Person.create({ firstName: "Jane", lastName: "Doe" })
Then, in an Ember view, you could write something like:
<p>{{person.fullName}}</p>
…and the view would automatically updated whenever firstName or lastName changed. Similarly, you could edit firstName using the following code:
{{view Ember.TextField valueBinding="person.firstName"}}
In this example, changes to the text field will be automatically propagated back to the underlying object. (Though you can get clever and build a text field that only propagates changes when the user is done editing.)
If you need to pass property updates from Ember to QT, see the guide to building getters and setters with computed properties or use observers. A lot depends on exactly how you're exposing your C++ APIs via your JavaScript bridge. But as long as you can tie into Ember.Observable somehow, you'll have full access to all of Ember's features.

Related

How to build a meta-driven application in emberJS

Note: The English used in this article (along with the terms) may be a bit "out of order" since my native language is not English. Rest assured I have tried my best to make it as readable as possible, and if I have missed anything please do comment before downvoting so I may update the question accordingly (I'm still new to this)
So I've searched most of the internet for a solution to this, to find a tutorial that would guide me on the metadata driven approach for building an application on EmberJS. The documentation on Ember doesn't explain anything about the approach, just a function definition of extractMeta here, and a basic overview of how to handle metadata here.
What I want to achieve is to build a portal, with Sugar as the back-end for the application. The application will use REST API for making calls to extract the data as well as the metadata of the application. We want to make the application generic, so that no matter what module is called, the metadata is extracted to determine the fields required in the model, a filtered portion of the data needed from the call is populated into the model accordingly and the is displayed in a generic template, that will be global and used throughout the application.
The metadata includes various items such as buttons, panels, attributes(each with multiple layers of data within) etc, each may be used once or multiple times within the call or not at all. For example, for displaying the application would require the attributes for display within the table, as well as buttons for adding, deleting updating etc. Upon click the panel may be required for say, adding a particular record, which itself may contain various fields.
As an example, is the default Sugar instance that shows the leads in the data, notice how it contains various components.
Here, another example, of the panel that appears when I click the create button in the leads list, notice the fields that appear within the panel
Please Note that I do understand how to make the REST API calls for the data as well as the metadata. But how to turn that into a generic meta driven application is what I am struggling with. Thanks in advance!
If I understand this correctly, you're looking for some kind of generic UI builder based off of returned data from a REST endpoint. Ember provides the component helper.
The {{component}} helper can be used to defer the selection of a
component to run time. The {{my-component}} syntax always renders the
same component, while using the {{component}} helper allows choosing a
component to render on the fly. This is useful in cases where you want
to interact with different external libraries depending on the data.
Using the {{component}} helper would allow you to keep different logic
well separated.
{{#each model as |post|}}
{{!-- either foo-component or bar-component --}}
{{component post.componentName post=post}}
{{/each}}
Read here for a more thorough explanation.
What you essentially need to do is build a bunch of different components for each of the possible attributes from the metadata. Your models will contain what components they should render and you'll use the component helper to dynamically render the correct elements.
If you're using a table based approach, have a look at ember light table. They leverage this approach heavily with how they build the columns for their tables and support custom components:
columns: computed(function() {
return [{
label: 'Avatar',
valuePath: 'avatar',
width: '60px',
sortable: false,
cellComponent: 'user-avatar'
}, {
label: 'First Name',
valuePath: 'firstName',
width: '150px'
}];
})
As you see here, the columns are rendered generically and they use the cellComponent property to determine which component type to render.

How can I model singletons without an id in ember?

I am new to ember and am trying to migrate an existing application, and would like to know what the recommendation is for modeling a single object that will be reused in multiple components on every page. ie: As part of the initial load, I would like to perform a GET request against a URL like 'https://example.com/currentUser' and get an object back like:
{
name: "Users Name"
email: "user#email.com",
profileImg: "http://example.com/pictureOfUser.png"
... snip ...
}
This object will then be used in components for menus, toolbars, and a form for updating it via a post to the same URL.
What is the best way to model this workflow in ember? Given that this is an incidental object and not the focus of most routes, it does not seem to make sense to specify it as the model of them. Also, does ember data handle cases where a model is a singleton and does not have an ID, or would I need to use something like Ember.$.ajax ?
What do you mean by "where a model is a singleton"?
If you use the ember-data default adapter, then yes, a model needs to have an ID, it's part of the JSONAPI spec. If you already have a backend with different conventions, take a look at extending or swapping out the default adapter.
A service is a singleton, and there is nothing preventing you from making an AJAX call there. You would be losing out on all the nice things that come along with ember-data, but, you can do it.

filtering hasMany association in Ember

I'm brand new to Ember and stuck on something that seems very basic. So far in my e-commerce application, I have two models, Product, and Style; a Product has many Styles. For each product, I want to list a subset of the styles (e.g., those that are in stock or out of stock). Coming from a Rails background, I thought I would create a model method in Product called stockedStyles, which filters its styles and returns only those with stocked=true. That didn't work, so I tried another approach of using a controller method, but struck out there too.
Here's the code so far: http://jsbin.com/mufumowabi/1/edit?html,js,console,output
While I would definitely like to know the best practices way of doing this, I'm also curious about other approaches people can suggest that would work but are not recommended -- and why they aren't recommended. Especially when I'm learning something new, I like knowing all the different ways you could do something and then choosing the best/cleanest one.
If there's a tutorial that covers this sort of thing, please send it my way. I couldn't find anything that does this sort of thing, even though it seems so basic.
Lastly, I've found debugging Ember to be somewhat of a black box. For example, for the non-working code posted here, the JS console just says "error". Tips on how I would get more information about why what I'm doing is wrong would be most appreciated as well.
TIA,
fana
I feel your pain. I too came from a rails background expecting similarities in the implementation only to get confused initially. Nobody is ever exaggerating when they claim Ember requires a very large learning investment, but trust me if you stick around it's totally worth it.
Real quick let's take care of a simple goof: You can assign an object property to be either Ember.computed, or function() { /***/ }.property('sdf'); You can't have both. So make that computed function either:
unstockedStyles: Ember.computed.filterBy('styles', 'stocked', false);
or
unstockedStyles: function() {
return this.get('styles').filterBy('stocked', false);
}.property('styles.#each.stocked')
but you can't do both at once.
Ember Models vs Rails Models
Next, the difference with Ember, coming from rails perspective, is that models in Ember.js are intended to be extremely light, serving only as a minimal binding between the data source and the framework overall. Rails takes quite literally the opposite approach, encouraging a very heavy model object (and this is still a large source of contention in the rails community).
In ember.js, the model method helpers are intended to be placed in the controller objects (again, counterintuitive coming from rails). Moving that out, you'll want your models to look like this:
App.Product = DS.Model.extend({
title: DS.attr(),
styles: DS.hasMany('style', { async: true })
});
App.Style = DS.Model.extend({
desc: DS.attr(),
stocked: DS.attr("boolean")
});
The reason for this difference from Rails is that the role of controllers in Ember.js is for "decoration" of your object, whereas in Rails its to handle incoming/outgoing data logic. For each page, you may want to render the same data in different ways. Thus, the model will remain the same, and the controller takes on the burden of encapsulating the extra fluff/computation. You can think of decoration in the same way you were taught the inheritance pattern in OO, with a slight twist:
Let's say you want to have a Person base class (your Ember model), but then you extend it to Teacher and Student subclasses (your controllers) in order to add an additional propertiy that may be from the same type but is not modeled in the same way. For example, Teachers and Students have a many-to-many relationship to courses, but you want to model Students as attending their courses, where Teachers are instructing them. The controller acts as a way to provide such a filter.
ArrayController vs ObjectController
As for the controllers, computed properties for individual records should be placed in the ArrayController's associated ObjectController (we'll call it ProductController), so your controllers now look like this:
App.IndexController = Ember.ArrayController.extend();
App.ProductController = Ember.ObjectController.extend({
unstockedStyles: Ember.computed.filterBy('styles', 'stocked', true)
});
Finally, while Ember.js can automatically associate ObjectControllers with their associated ArrayController for resources defined in your router, you're loading a Product array on the IndexController, so you need to tell IndexController to use ProductController for its item behavior:
App.IndexController = Ember.ArrayController.extend({
itemController: 'product'
});
App.ProductController = Ember.ObjectController.extend({
unstockedStyles: Ember.computed.filterBy('styles', 'stocked', true)
});
Handlebars Binding
Not much here except for a small mistake: while you've enabled a computed property correctly in the proper controller, your {{#each}} loop is instead bound to the original styles array. Change it to use the new property:
{{#each unstockedStyles}}
<li>
{{desc}}, in stock: {{stocked}}
</li>
{{/each}}
And now you're good to go!
JSBin of fixes here: http://jsbin.com/sawujorogi/2/edit?html,js,output

get all bindings of templete in ember

Is there a way to get all bindings of all fields or checkboxes of a template in ember ?
The intention is to get them in a generic way, to store them in a generic way in a json object and to send them to the server. The server maps the variable names to the model attributes. Something like I call a function from the controller with the template name and get back all bindings ?
get_bindings("templatename":"test_template")
How should this method look like ?
This is really the purpose of two-way bindings in Ember. When you have an object that looks like...
person = Ember.Object.create({
name: 'Jane',
age: 25
});
and a template that looks like...
<div>Enter your name here: {{input value=person.name}}</div>
<div>Enter your age here: {{input value=person.age}}</div>
...then when you type something new in the boxes, your person object automatically gets updated. To persist your person, all you have to do is serialize the person object and send it off to the server. There's no asking the template for the new values or manually synchronizing the two.
If you are looking for a more sophisticated way of managing local model lifecycle and interacting with a server that follows certain JSON conventions, check out Ember Data or any of the other maturing data persistence libraries that are popping up.
Ember doesn't give you a way to easily interact with the view from the controller by design.

Ember Data and Northwind OData

Could Ember-Data b3+ be used for work against a service like this, http://services.odata.org/V2/Northwind/Northwind.svc. If so, could anyone provide an example on how to use it to read OData.
For example a JSBin showing a list of customers where a customer list item can navigate to the orders of a clicked customer
I think this would be a great boon for developers working against different data protocols to wrap their heads around how to wire up an Ember application with Ember-Data.
I've done this with fixtures but just couldn't really wire it up with actual server data.
Edit
Since I wrote this, I have abandoned Ember and fell back to angular for my SPA data apps. The main reason behind this is Ember Set which you should use for Ember to wire up all its binding internals.
Unfortunately, this is not compatible with most libs like Jaydata or Breeze. At least not when you wish to make changes/saves to your entity service.
Jaydata and Breeze both use a propertyChanged property to monitor changes to your entity and Ember will prevent these changes with a You should use Ember Set error.
I could probably have written some sort of adapter to overcome this problem but really I didn't have time and I use a library "Ember" to make my life easier... not to have headaches on basics such as Data Service Queries.
So... I really love Ember, but unfortunately as long as they dont enhance "Ember Data" or drastically change the Ember Set policy, I can't use it!
Basically, if you plan to use a data library (JayData, Breeze) to update a backend...
DON'T USE EMBER!
Original
I had a look (very quickly!) at ember-data and wasnt thrilled really! It looks promising for Standard REST service which IMHO is not WCF's case.
I ended up using JayData for that purpose and I must say it integrates very well with Ember.
here is a quick snippet to get you going:
//Instanciate the Ember APP
App = Ember.Application.create();
//Tell the APP to initialize but to wait before launching
App.deferReadiness();
//Setup your JayData Store
//Entities.EntityModel was generated by JaySvcUtil
App.myStore = new Entities.EntityModel({
name: 'oData',
oDataServiceHost: <YOUR_WCF_ENDPOINT_URL>
});
//Create your route and populate model data
App.IndexRoute = Ember.Route.extend({
model: function () {
//This passes the toArray() promise to the model
return App.myStore.People.orderBy('it.Name').toArray();
}
});
//When JayData Store is ready, Fire the App
App.myStore.onReady(function () {
App.advanceReadiness();
});
Ember Route Model actually handles the promise given by JayData which allows us to just pass the query. see: http://emberjs.com/guides/routing/asynchronous-routing/#toc_the-router-pauses-for-promises