Our very own Anthony O’Sullivan gives his fresh, punny, and appropriately detailed take on Vue.js and we couldn’t have had more fun!
Your partners in accelerated digital transformation
Our very own Anthony O’Sullivan gives his fresh, punny, and appropriately detailed take on Vue.js and we couldn’t have had more fun!
This post is another by InRhythm’s own Jack Tarantino. For the full post and additional links, check out the original “Frameworkless JavaScript Part 3: One-Way Data Binding” on his website.
1-way data-binding is “a method of putting data into the DOM which updates whenever that data changes”. This is the major selling point of the React framework and with a little effort you can set up your own data binding with much less code. This is particularly useful when you have an application that sees routine changes to data like a simple game, a stock ticker, or a twitter feed; objects needs to have data pushed to the user but no user feedback is required. In this case, we need an object with some data in it:
let data_blob = {
movie: 'Iron Man',
quote: 'They say that the best weapon is the one you never have to fire.'
}
A Proxy:
const quote_data = new Proxy(data_blob, {
set: (target, property, value) => {
target[property] = value
console.log('updated!')
}
})
And a poor DOM node to be our guinea pig:
<p class="js-bound-quote">My favorite {{ movie }} quote is "{{ quote }}".</p>
In this case, we need the data_blob
to serve as a storage unit for the proxy. Proxies in ES6 are a convenient way to trigger callbacks when certain actions are taken on an object. Here, we’re using the proxy to trigger a callback every time somebody changes a value in the data blob. We don’t have a way to update the text in the DOM node yet though so let’s set that up:
const quote_node = document.querySelector('.js-bound-quote')
quote_node.template = quote_node.innerHTML
quote_node.render = function render (data) {
this.innerHTML = this.template.replace(/\{\{\s?(\w+)\s?\}\}/g, (match, variable) => {
return data[variable] || ''
})
}
This gives us a quick and dirty way to update the node’s inner HTML with some arbitrary data. The only thing needed to connect our new script with the proxy is to substitute the console.log
call with quote_node.render(data_blob)
:
const quote_data = new Proxy(data_blob, {
set: (target, property, value) => {
target[property] = value
quote_node.render(data_blob)
}
})
With all this setup, we can add a quick script to prove that our DOM node is, in fact, updated every time we change the data blob. The exact same way that we want things to happen with a framework but with no external dependencies and WAY less code.
const quotes = [
"What is the point of owning a race car if you can't drive it?",
"Give me a scotch, I'm starving.",
"I'm a huge fan of the way you lose control and turn into an enormous green rage monster.",
"I already told you, I don't want to join your super secret boy band.",
"You know, it's times like these when I realize what a superhero I am."
]
window.setInterval(() => {
const quote_number = Math.floor(Math.random() * quotes.length)
quote_data.quote = quotes[quote_number]
}, 2000)
This adds a script to change to a random quote every two seconds. Check out the working example below:
This is a little sloppy, as it only works for one node, one time. Let’s clean things up a bit and add constructors for both the nodes and Proxies. Continue reading on jack.ofspades.com…
Listen to Andy Philbert Jr. – Head Javascript Recruiter of InRhythm, deliver an insightful talk on what his kind look for when interviewing and hiring.
From Andy:
“Recruiters are usually the first people you speak to when interviewing with companies. We are not engineers and screen for non technical qualities that shows that you would be someone amazing to work with and have the potential to be or already are a great engineer. This talk discusses the recruiter’s role within the interview process and how to market yourself as a great engineer without having to rely on just showing your code.”
Session: IR Lightning Talks 1 – Aug 24, 2017, IR HQ
[huge_it_slider id=”3″]
Last week, driven by the feedback from our engineering leadership team, we held InRhythm U’s first-ever Code Lounge, inviting everyone from across the company and a few external guests to learn new skills, brush up on existing ones, or just get help on a personal project.
Code Lounge featured technical “stations” for Angular, React, React Native, Express, Vue, Node.js, Java, QA, UX and Product, each led by an InRhythm senior developer instructor. Accompanied by food and drinks on the company, the event provided an easy atmosphere and low-key way for everyone to network and learn a thing or two!
Here are a few key takeaways and learnings from Code Lounge:
At InRhythm, our goal is to give our people the best opportunities for learning and growth. This goal is something I feel very passionate about as do all our senior leaders across the organization. Code Lounge is just one example of how we keep our company culture and ourselves at the top of our game! If you want to find out more, visit us at www.inrhythm.com.
The browser provides powerful tools for debugging web applications, including those built with Angular 1. I’ll list a few important concepts, but for an in-depth tutorial on debugging JavaScript in the console I highly recommend reading through the DevTools documentation on developers.google.com.
Commonly, you might set breakpoints to explore the code and check the value of variables mid-execution. You can set breakpoints for certain types of event handlers, on particular lines, or for the browser to pause execution for any exception. Once paused, you can inspect the value of variables visible from that line in the function’s scope, step over/into function calls. You can review stack traces and even auto-format poorly formatted or minified code.
While paused at a breakpoint you can execute any valid JavaScript expression from that context. DevTools also allows you to write and save commonly used snippets if you have long or complex debugging scripts that you find yourself copying and pasting regularly to the console.
Despite its power, there are times when the debugger is too low-level a tool for debugging an Angular application. From a breakpoint, you only have visibility into local, closed over, and global variables which are visible from the currently executing line of code. You can gain a wider view by traversing the call stack or stepping into functions, but it can take a lot of time and exploration to find information relevant to the bug you are fixing.
Additionally this gets even more difficult, when code is minified and source maps aren’t available, or when debugging someone else’s application whose code you’re not familiar with.
Thankfully, Angular exposes some helpful interfaces to inspect the state of the application. With the three tricks below, you can potentially save yourself hours of time debugging from the browser console.
Recently, a friend asked me to help debug their Angular 1 application but I didn’t have immediate access to the source code and the deployed code was minified without source maps. Exploration via breakpoints was almost impossible, so to get quick snapshot of the application, I ran the command below which listed all of the providers registered on the main module.
// from http://stackoverflow.com/a/27533937
angular.module('MyApp')['_invokeQueue'].forEach(function(value){
console.log(value[1] + ": " + value[2][0]);
});
For illustration, here is the same statement executed against the Angular 1 TodoMVC app to list its controllers and providers:
> angular.module('todomvc')['_invokeQueue'].forEach(function(value){ console.log(value[1] + ": " + value[2][0]); }); register: TodoCtrl factory: todoStorage factory: api factory: localStorage directive: todoFocus directive: todoEscape <- undefined
This snippet has come in handy many times. Have you ever seen the error Error: Unknown provider: myApiProvider <- myApi,
and you could swear that yes, you do have a provider called myApi
? Typos happen and they can be maddening to track down. Using the snippet above to list the registered providers has saved me hours diagnosing these kinds of mistakes.
Let’s say we want to inspect the TodoMVC api
factory from the console to validate that it is working as intended. One option would be to set a breakpoint on a line where a reference to api
is in scope and then log it to console. Alternatively, we can get a reference to $injector
from the console and ask it to give us a reference to api
, or any other provider for that matter.
var service = angular.element(document.body).injector().get('serviceName')
Once we’ve captured a reference to a provider, we can inspect its public methods and properties:
> var todoApiService = angular.element(document.body).injector().get('api') <- undefined > todoApiService <- Object api: Resource(value) clearCompleted: () delete: (todo) get: () insert: (todo) put: (todo) todos: Array[0] __proto__: Object
Now we can actually directly call the api
service’s public methods to see if it’s working as intended. For example, we could call todoApiService.clearCompleted()
and see how that action propagates through the application.
Unlike providers, controllers are not registered on the application’s $injector
instance. Providers are instantiated one time and then cached by the $injector
. The cached instances are injected as needed into functions. Because service instances are shared across every function that injects that service they are ideal for storing shared state. This application design pattern is very common and known as the singleton pattern.
Controllers are not singletons. Angular instantiates a new controller every time a controller is bound a scope. You can also directly instantiate a controller and it’s very common to do so in unit tests. So, when debugging a page you don’t want just any controller, you want a particular instance of a controller which is bound to a particular scope in the DOM.
There are two (or more) ways to inspect a particular controller. The first is via a helpful hook provided by DevTools. If you type $0
into the browser console, it will return a reference to the DOM node currently selected DOM element in the “Elements” tab. To begin, select an element whose controller you want to inspect:
Then via the console execute this line:
// from http://stackoverflow.com/a/22799606 angular.element($0).scope()
Alternatively, you can use document.querySelector
to target an element and use the same code snippet:
> angular.element(document.querySelector('ng-view')).scope() <- Scope {$$childTail: ChildScope, $$childHead: ChildScope, $$nextSibling: null, $$watchers: Array[13], $$listeners: Object…}
Once you’ve captured a reference to the controller for a particular element, you can inspect the scope and any properties attached to the controller itself and even explore up and down the scope tree to look for shadowed properties and explore child scopes.
Hopefully these tricks help you to explore and debug Angular 1.X applications more effectively. For advanced debugging and performance tuning, try out AngularJS Inspector, ng-stats and other libraries designed specifically for debugging Angular applications.