In a couple of apps I’ve worked on, we’ve used the jQuery plugin X-Editable for entering values instead of bulky textboxes. X-Editable works nicely with Bootstrap and pops-up an editor in order to fill in a value. If you aren’t familiar with X-Editable, I encourage you to check out their demos. Figure 1 shows a simple screenshot of what a typical pop-up looks like.
Figure 2 shows that X-Editable can also do inline forms if you choose instead of a popup.
X-Editable works great, but what if you want to use it with Ember? That’s where I ran into a problem. You see, X-Editable changes the value that you have for you. We don’t want that. We want it to flow through Ember so everything is properly bound. Let’s start with how we might accomplish this goal.
X-Editable and Ember Binding
The first step is to setup a link for X-Editable. In this tutorial we’ll use a simple textbox, but the concept should work with other types of editors (e.g. date picker). Below is the HTML code (using Handlebars) for a simple X-Editable link.
This alone doesn’t give us enough information in order to update a model. I added in a
data-id attribute that I could use in order to set the proper model property. Within it, I simply put in the name of the property that I’m going to want to set (in this case,
name). With that added in, we have our final link.
.editable elements using a bit of jQuery, but not so fast. We’re in an Ember application. Where should we do this? I created an
Ember.View to handle this for my template. From there, I hooked into the
didInsertElement method on the VIew.
That call to
editable is how we’d normally wire-up our X-Editable links. In our case though, we’re going to want to hook into X-Editable’s
success method in order to update our model. Adding in that code gives us the following.
success method in place, we now are updating our model with Ember. This works perfectly.
A Little Problem
For those of you running Ember 1.7 and below, there is still one little problem. Our value isn’t always kept up-to-date when dealing with a value inside a Handlebars expression. This doesn’t seem to happen with Ember 1.8 and above (because it uses new metal views), but I found an issue using 1.7 and below because the views use
script metamorph tags to keep values up-to-date. If you aren’t sure what I mean, let’s look closer at Ember 1.7 vs 1.8.
Big Changes From Ember 1.7 to 1.8
When using Ember 1.7, when you create a simple Handlebars tag, like so:
It ends up yielding the following HTML code.
Notice that our value has been wrapped in
<script id="metamorph-2-start" type="text/x-placeholder"></script> and
<script id="metamorph-2-end" type="text/x-placeholder"></script>. This is how Ember used to keep track of values in your application.
With Ember 1.8 and above, the results are MUCH cleaner.
These are called “Ember Metal Views” (you may have heard them called “HTMLBars” as well, as that is what they were called during development).
X-Editable and the Ember 1.7 Problem
This problem affects all versions of Ember prior to 1.8. Continuing with our “Amount” example, let’s make that value editable using X-Editable as we saw previously. We’re also going to use a Handlebar helper that formats the value to US currency, adding commas to the value. It is called
formatCurrency, but its implementation doesn’t matter for our example. Below is the Handlebars code.
Now remember, in Ember 1.7, our call to
formatCurrency amount will be wrapped in
script metamorph tags. Meaning that there is now HTML content INSIDE our X-Editable tag. This looks like so:
When we change the value of
amount in this scenario, we get an unexpected surprise (Figure 03).
What is the error
Uncaught Error: Cannot perform operations on a Metamorph that is not in the DOM. telling us? No guesses? This error is coming from our helper method, but why?
What’s happened is that X-Editable changes the value in the HTML for us, replacing the content between the
a tags, thus stripping out the
script metamorph tags that Ember 1.7 (and below) need to update the value. Thankfully there is a way to tell X-Editable to stop this behavior. It took me a good long time to figure out how to accomplish this, but looking at the docs gave me the answer. The
display callback can be overridden to
return false, thus meaning “no displaying methods will be called, element’s text will never change.” Perfect! Let’s add in that code to our
IndexView giving us the final code that supports both 1.8 and below.
That’s a Wrap
I hope you found this post helpful. We learned a bit about the inner workings of Ember, and the difference that 1.8+ brought to our views. We also learned how to use X-Editable successfully with Ember. If you want to play around with some source code, here is a CodePen that you can mess around with. Try changing the Ember version to 1.7.0 and you’ll see that the code works as expected.