Fixing Jasonette: the Confusing Parts.

Ethan
6 min readApr 16, 2018

--

Recently I sat down and looked into some features and previous design decisions that made Jasonette needlessly more confusing that it needed to be, and fixed them. Here are the three:

  1. No more “String only” policy
  2. No mandatory requirement for “head”
  3. No more confusing tab bar

1. No more “String ONLY” policy

Anyone who’s had to deal with Jasonette templates will appreciate this a lot. Previously, a lot of confusion and annoyance came from the fact that you had to turn everything into string before rendering.

For example, something like this would crash the app because the 12345 is a number:

{
"type": "label", "text": 12345
}

You had to put everything in double quotes to turn them into string before rendering, like this (Notice 12345 is now "12345"):

{
"type": "label", "text": "12345"
}

This was especially annoying when using template expressions. Take a look at this example:

{
"type": "label", "text": "{{$jason.balance}}"
}

This markup would also crash the app if the evaluated value of $jason.balance was a number (for example 100) or boolean (true or false)

So the only way to make this work without crashing was to turn it into string by using the toString() JavaScript method, like this:

{
"type": "label", "text": "{{$jason.balance.toString()}}"
}

This was annoying because a lot of people would try to render content fetched straight from an API, and many APIs return numeric values or boolean values. And when they tried to render it, it would always crash because they didn’t turn the number or boolean values into string.

This needed to be fixed. So as of today, it’s fixed, both on iOS and Android.

You no longer need to assume everything is a string (or turn everything into string format) when using Jasonette. I’m sure this will get rid of all the confusion, as well as make the markup much cleaner (because you don’t have to stringify every time).

Everything should just work, right out of the box. Here’s an example (The text attribute is a number, and the style.height is also a number):

{
"$jason": {
"body": {
"sections": [{
"items": [{
"type": "html",
"text": 123455,
"style": {
"height": 200
}
}]
}]
}
}
}

To take advantage of this update, just make sure to update to the latest version of Jasonette and you’re all set to go, no need to change anything!

2. No mandatory requirement for “head”

The $jason.head attribute is used to define useful features like template, data, and metadata like title and description. Previously including the head attribute was a mandatory requirement — the app wouldn’t render at all if you didn’t include the attribute.

This was confusing for many beginners and those who didn’t really care about including these metadata. While recommended, these are not something that should be forced upon (Just like how you don’t need to include <head> tags in an HTML document)

Anyway, this rule is now gone. Now a markup like the following — with no "head" — will render just fine:

{
"$jason": {
"body": {
"sections": [{
"items": [{ "type": "label", "text": "Hello World" }]
}]
}
}
}

3. No more confusing tab bar

To explain this I first need to explain one fundamental design decision that makes Jasonette unique.

A. What you should know about “page-oriented model” and Tab bars

Jasonette is “page-oriented”. You can learn more about it here:

Unlike conventional mobile app development approaches where the developer must think about an app as a monolithic single entity, the whole point of Jasonette is that everything is broken down to standalone sandboxed “pages”, kind of like how HTML web pages work.

This means that every view gets constructed from scratch completely independently from one another.

To use the web page analogy, imagine what it would be like if you visited web page A, then clicked a link to visit page B, but some of the HTML elements remained and carried over to page B. This is NOT desirable, and NOT how web browsers work. All browsers handle every web page independently.

Same goes for Jasonette. On Jasonette, if you want a view to have three tab bar items, you MUST have three tab bar items in the JSON markup.

Which brings us back to the tab bar issue. Let’s say we have a view https://app.url/1.json which contains the following markup:

{
"$jason": {
"body": {
"header": {
"title": "View 1"
},
"footer": {
"items": [{
"text": "Item 1",
"url": "https://app.url/1.json"
}, {
"text": "Item 2",
"url": "https://app.url/2.json"
}]
}
}
}
}

It’s a view that contains two tab bar items. When you tap the first tab bar item, it will lead you to 1.json (the same view) and tapping the second item would lead you to 2.json.

What would happen when you click the Item 2 and it turns out that the https://app.url/2.json contains the following markup?

{
"$jason": {
"body": {
"header": {
"title": "View 2"
}
}
}
}

Here, no footer exists, and following the “page oriented rule” I mentioned above, this view will NOT have the footer items. The tab bar items would be gone, and you’d have no way to go back to view 1.

This is why the framework previously enforced some requirements. The next section talks about these requirements.

B. Some confusing parts about tab bars

A. If you didn’t include url for tab bar items, the entire view wouldn’t render at all

Previously, every tab bar item had to have a url attribute. For example, the following markup would be an error because the tab bar items don’t have a URL:

{
"$jason": {
"body": {
"footer": {
"items": [{
"text": "Item 1"
}, {
"text": "Item 2"
}]
}
}
}
}

The rationale was “why would you want to have a tab bar if you can’t navigate to it?”. This is still a 100% valid question and you should still have the url attribute for all items.

But this also doesn’t mean that it needs to be strictly enforced. This turned out to be too confusing for new users, because if you didn’t have those url attributes defined, the framework would just completely blank out, displaying nothing.

Now this rule is gone. So above markup will work. (Although you really should still include URLs for the tab bar items if you want it to do anything)

B. Having an incorrect URL would also block rendering altogether

The framework would also break if any of the tab bar items had incorrect URLs. This included cases like:

  1. The first tab bar item’s URL doesn’t match the view it loads from.
  2. The url was not a valid URL with valid JSON

Here’s an example:

{
"$jason": {
"body": {
"footer": {
"items": [{
"text": "Item 1",
"url": "blahblah incorrect url"
}, {
"text": "Item 2"
}]
}
}
}
}

This rule is also gone, now the view will load even with incorrect URLs. But again, you should really have correct URLS eventually. This is just to get rid of confusion.

Conclusion

These were not so difficult to fix but I think these small things make a huge difference for developers because it’s not easy to figure out what went wrong if the app completely blanks out or crashes.

The general theme of these “fixes” is to move away from the “spartan” strict rule enforcements and get rid of all the confusing parts as much as possible. It’s also in line with web browser implementations which had great influence on Jasonette’s design principles.

I plan on looking for these little confusing parts as much as I can and fixing them. You can help by:

  1. Sharing some of the confusing or annoying parts you often encounter with Jasonette
  2. Sending pull requests to the following repository which will be used to keep track of all these edge cases

I realize how these small things really matter, so please let me know.

You can find me at:

Jasonette Twitter: https://twitter.com/jasonclient

Personal Twitter: https://twitter.com/gliechtenstein

Forum: https://forum.jasonette.com

Medium: https://medium.com/@gliechtenstein

Subscribe to Newsletter: https://docs.jasonette.com/#mc-embedded-subscribe-form

--

--