Cutter's Crossing - ES2015https://www.cutterscrossing.com/index.cfm
We talk about web development, often covering the three core pillars: HTML, CSS, and Javascript. There is a lot of legacy content here, discussing everything from ColdFusion to ExtJs, as well as more current stuff like modern EcmaScript, etc.en-usSun, 15 Sep 2019 15:35:23 -0000Wed, 29 May 2019 23:12:00 -0000BlogCFChttp://blogs.law.harvard.edu/tech/rssweb.admin@cutterscrossing.comweb.admin@cutterscrossing.comweb.admin@cutterscrossing.comnoJS Tip: Simple Array Of Unique Itemshttps://www.cutterscrossing.com/index.cfm/2019/5/29/JS-Tip-Simple-Array-Of-Unique-Items
A co-worker showed me a simple trick for getting an array of unique, simple values. Let's say we were combining two arrays of message id's:
<code>
let arr = [19,22,7,12,6,85];
let arr2 = [22,8,3,19,45];
let newArr = [...arr, ...arr2];
// newArr equals [19, 22, 7, 12, 6, 85, 22, 8, 3, 19, 45]
</code>
This gives us a new array, combining the values of the first two. But, we often only want the unique values. Rather than looping over every item, checking for dupes, etc, we can take advantage of the new <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Set" target="_blank">Set</a> object. A `Set` lets you store unique values of any type, and automatically tosses duplicates. As an iterable, it's easy to convert it from an Array like object to a true array.
<code>
newArr = Array.from(new Set(newArr));
// newArr now equals [19, 22, 7, 12, 6, 85, 8, 3, 45]
</code>
And, being an array of numerics, we'd likely want to sort it in numeric order. We can do this with <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array/sort" target="_blank">Array.sort()</a>.
<code>
newArr = Array.from(new Set(newArr)).sort();
// Not exactly, now it reads [12, 19, 22, 3, 45, 6, 7, 8, 85]
</code>
OK, so that seems a little weird, until you read that documentation for `sort()` that I linked to above
<blockquote>
The default sort order is built upon converting the elements into strings, then comparing their sequences of UTF-16 code units values.
</blockquote>
Well, that seems a bit of a bummer. But, you can get around this by using the optional `compareFunction` argument of the `sort()` method.
<code>
newArr = Array.from(new Set(newArr)).sort((a,b) => a - b);
// That's better! Now it reads [3, 6, 7, 8, 12, 19, 22, 45, 85]
</code>
And there you have it. Simple, unique value array. The `Set` object allows for any type, so you <em>could</em> use complex objects as well, but again you would have to provide a custom `compareFunction` for handling the `sort()`.
DevelopmentES2015JavaScriptWed, 29 May 2019 23:12:00 -0000https://www.cutterscrossing.com/index.cfm/2019/5/29/JS-Tip-Simple-Array-Of-Unique-ItemsFun With Destructuringhttps://www.cutterscrossing.com/index.cfm/2019/5/16/Fun-With-Destructuring
If you aren't compiling your JavaScript (well, EcmaScript...) code with Babel, you're probably missing out on some of the best features of the evolving language. On the other hand, if you're working in React or Angular every day, you've probably come across some of the most dynamic features. Destructuring is a prime example, but it's also important to understand the "gotchas".
Let's take a simple example to show you some of the power of destructuring.
<code>
const nodes = [{
id: '0-1',
label: 'Led Zeppelin',
members: [{
id: '0-1-1',
label: 'Jimmy Paige'
}, {
id: '0-1-2',
label: 'Robert Plant'
}, {
id: '0-1-3',
label: 'John Paul Jones'
}, {
id: '0-1-4',
label: 'John Bonham'
}]
}];
const band = nodes[0];
const { label: bandName, members } = band;
const [leadGuitar, leadSinger, bassPlayer, drummer] = members;
</code>
So, what's it do? Let's break it down. I took the first <em>node</em> and assigned it to <em>band</em>. I then assigned the <em>bandName</em> and <em>members</em> variables from the <em>band</em>'s <em>label</em> and <em>members</em> values, respectively. Then, I took the first four items from my <em>members</em> array, and assigned each of them to a variable as well. This offers you a lot of power, simplifies your code, and can save some CPU cycles as well.
But, what happens if something doesn't exist? Say you had a <em>band</em> with no members? (That's a trick), or <em>members</em> but no <em>drummer</em>? In those cases the <em>members</em> or <em>drummer</em> variables would be <em>undefined</em>.
Now, let's talk about "gotchas". Here's a neat bit of syntactic sugar for you.
<code>
drummer = {...drummer, deceased: true};
</code>
Using the spread operator, with destructuring, we add a new key to the <em>drummer</em> object. But, wait...
We also <strong>replaced</strong> the drummer object. This is important. While using destructuring like this can be easy, and very effective, it <strong>can</strong> have consequences. If you needed to update <em>drummer</em> <strong>by reference</strong>, you just killed the reference assignment.
And, the above statement would error (as will the array example below). This is because we declared <em>drummer</em> (and <em>members</em>) using <strong>const</strong>. While we could adjust, add, or remove keys and values, we can't <strong>replace</strong> the variable. We would have to declare using <em>let</em> instead of <em>const</em>.
The same holds true when using a spread operator and destructuring when attempting to update an array.
<code>
members = [...members, { id: '0-1-5', label: 'Jason Bonham' }];
</code>
While the <em>members</em> array now has a fifth item, the <strong>reference</strong> to <em>band.members</em> is no longer valid, as you <strong>replaced</strong> the variable.
But, this is no big deal, unless you needed to update the <em>reference</em> to the original variable. As long as you're aware of this limitation, it's easy to fallback on other methods to update those references. Let's change our variable declarations a little bit, and retool this code to work for us.
<code>
const band = nodes[0];
const { label: bandName, members } = band;
let [leadGuitar, leadSinger, bassPlayer, drummer] = members;
Object.assign(drummer, {deceased: true});
members.splice(3, 0, {id: '0-1-5', label: 'Jason Bonham'}); // insert Jason in the drummer array position
[,,,drummer] = members; // and update the declaration
</code>
We switched our member variable declarations to <em>let</em>, so they can be replaced, updated the <em>drummer</em>, inserted a new member in the correct position, and updated the <em>drummer</em> reference to the new member.
This post only briefly touches on the power of destructuring, in modern EcmaScript. For a fantastic overview, <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment" target="_blank">check out the MDN documentation</a>.
DevelopmentAngularJSES2015ReactNodeJSJavaScriptThu, 16 May 2019 14:52:00 -0000https://www.cutterscrossing.com/index.cfm/2019/5/16/Fun-With-DestructuringES2015 and Fun With Parametershttps://www.cutterscrossing.com/index.cfm/2015/11/20/ES2015-and-Fun-With-Parameters
If you've come to JavaScript after learning to program in other languages, one thing that's probably stuck in
your craw over the years has been the lack of any way to define default parameters in functions. You've probably
written something like this in the past:
<code>
var foo = function (bar) {
bar = bar || 'ok';
// ...
};
</code>
For the most part that sorta thing probably worked out, until your argument was a boolean, which then really
complicated things.
With ES2015, the heavens have opened and prayers have been answered, as we've finally been given the ability to
define default parameters. Consider the following:
<code>
// This is in a class
foo (bar=true) {
if (bar) {
console.log('First round is on Simon!');
} else {
console.log('No drinks today!');
}
}
</code>
Simple. We're saying that if <em>bar</em> is <em>true</em>, then Simon is buying, otherwise we're out of luck,
and defaulting our argument to true. We can then call this method a few times to test it out:
<code>
constructor () {
this.foo(); // 'First round is on Simon!'
this.foo(false); // 'No drinks today'
let bar;
this.foo(bar); // 'First round is on Simon!'
}
</code>
You can see from my comments what the output of those methods would be. It's important to note here that even
the <em>undefined</em> value passed as an argument triggered the default argument value as well.
Hopefully default arguments will help you to significantly simplify your code in the future. As usual, if you
have any feedback/praise/complaints/war stories, feel free to comment below, or drop me a private message
through the "contact" link on the page.
DevelopmentES2015JavaScriptFri, 20 Nov 2015 11:10:00 -0000https://www.cutterscrossing.com/index.cfm/2015/11/20/ES2015-and-Fun-With-ParametersES2015, Promises, and Fun With Scopehttps://www.cutterscrossing.com/index.cfm/2015/11/19/ES2015-Promises-and-Fun-With-Scope
I've been using Promises for some time now. JQuery has acted as a shim for some time, and several other libraries
have been around as well. ES2015 includes Promises natively. If you're unfamiliar with Promises, I strongly
suggest you <a href="http://www.datchley.name/es6-promises/" target="_blank">read this great post</a> by
<a href="http://www.datchley.name" target="_blank">Dave Atchley</a>.
Like I said though, I've been using Promises for a while now. So, when I started moving to ES2015 it was a bit
of a kick in the pants to find issues with implementing my Promises. Let me give you an example of how something
might've been written before:
<code>
'use strict';
module.exports = [
'$scope', 'orders', 'dataService',
function ($scope, orders, dataService) {
var self = this;
self.orders = orders;
self.addOrder = function (order) {
// ... do some stuff
// get original
dataService.get(order.id)
.then(self._updateOrders)
.catch(function (error) {
// do something with the error
});
};
// faux private function, applied to 'this' for unit testing
self._updateOrders = function (order) {
// ... some process got our order index from orders, then...
orders[index] = $.extend(true, orders[index], order);
};
}
];
</code>
Seems pretty straightforward, right? <em>addOrder()</em> gets called, which does some stuff and then retrieves
an order from the service. When the service returns the order, that's passed to the <em>_updateOrders()</em> method,
where it finds the correct item in the array and updates it (I know, it's flawed, but this is just an example to
show the real problem).
So, what's the problem? That works great. Has for months (or even years). Why am I writing this post? Fair
question. Let's take a look at refactoring this controller into an ES2015 class. Our first pass might look like
this:
<code>
'use strict';
class MyController {
constructor ($scope, orders, dataService) {
this.$scope = $scope;
const myOrders = [];
this.orders = myOrders.push(orders);
this._dataService = dataService;
}
addOrder (order) {
// ... do some stuff
// get original
this._dataService.get(order.id)
.then(this._updateOrders)
.catch(function (error) {
// do something with the error
});
}
_updateOrders (order) {
// ... some process got our order index from orders, then...
this.orders[index] = $.extend(true, this.orders[index], order);
}
}
MyController.$inject = ['$scope', 'orders', 'dataService'];
export {MyController};
</code>
That looks good, right? Well....
When <em>MyController.addOrder()</em> gets called, with this code, the <em>get()</em> method is called on the
service, and... BOOM! Error. It says there is no <em>_updateOrders()</em> on <em>this</em>. What? What happened?
Well, it's not on your scope. Why? Because ES2015 has changed how scope is handled, especially within the context
of a class. "this" is not the same in the context of the Promise's <em>then()</em>, at this point. But then, how
are you supposed to reference other methods of your class?
Bom! Bom! BAAAAHHHHH! Use an arrow function. "Wait? What?" (lot's of confusion today) That's right, an arrow
function. From <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions"
target="_blank">MDN</a>:
<blockquote>
An <strong>arrow function expression</strong> (also known as <strong>fat arrow function</strong>) has a shorter
syntax compared to function expressions and lexically bind the this value (does not bind its own this,
arguments, super, or new.target). Arrow functions are always anonymous.
</blockquote>
If you aren't still confused at this point you are a rockstar. Basically what it says is that <em>this</em> will
become of the context from which you're using the arrow function. So, in terms of a Promise, if we change our
<em>addOrder()</em> method like this:
<code>
addOrder (order) {
// ... do some stuff
// get original
this._dataService.get(order.id)
.then((order) => this._updateOrders(order))
.catch(function (error) {
// do something with the error
});
}
</code>
This then fixes our <em>this</em> scoping problem within our <em>then</em>. Now, I know this isn't much in the
way of an explanation into "How" it fixes it (other than setting the right <em>this</em>), and I know I'm not
explaining what an <a href="https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions"
target="_blank">arrow function</a> is either. Hopefully this is enough to stop you from banging your head against
the wall anymore, provides a solution, and gives you some clues on what to search for in additional information.
So, as always I welcome your feedback/suggestions/criticisms. Feel free to add a comment below, or drop me a
direct line through the "contact" links on this page.
DevelopmentAngularJSES2015JavaScriptThu, 19 Nov 2015 10:26:00 -0000https://www.cutterscrossing.com/index.cfm/2015/11/19/ES2015-Promises-and-Fun-With-ScopeDeath to Var - Why Let and Const Really Interest Me In JavaScripthttps://www.cutterscrossing.com/index.cfm/2015/11/18/Death-to-Var--Why-Let-and-Const-Really-Interest-Me-In-JavaScript
Today I want to talk about the value of ES2015's new <em>let</em> and <em>const</em> variable declarations, and
give you some use case scenarios. But first, let me tell you why I was really looking at all.
<a href="http://bennadel.com" target="_blank">Ben Nadel</a> is one of my favorite people. You will not, ever,
meet a nicer guy. Ben is the kind of guy that if the two of you were walking down the street in a blizzard, and you
were cold, he'd give you the shirt off of his own back and go topless so you wouldn't freeze. Yes, he really is
that nice of a guy.
I'd like to say that I've learned many things from Ben over the years. He blogs about everything as he learns
it, sharing what he finds along the way. And he's the first to tell you that he's not always right. Sometimes the
comments to his posts are even more informative than the posts themselves. And, sometimes, he gives his opinion
on a matter of programming and that opinion might not always follow best practice.
About a week ago, Ben posted an article titled <a href="http://www.bennadel.com/blog/2949-var-for-life---why-let-and-const-don-t-interest-me-in-javascript.htm"
target="_blank">Var For Life - Why Let And Const Don't Interest Me In JavaScript</a>. He's very clear, in his post,
saying that his article is an <strong>opinion piece</strong>. His thoughts are clear, his examples make sense, and
it's easy to see where he's coming from. You'll also find some really thought provoking discussion in the comment
thread both for and against.
But I think it's important to truly explore these new constructs in JavaScript. They were introduced with one
true goal in mind: to help manage memory in our applications. With the proliferation of JavaScript based applications,
both client-side and server-side, the need to carefully analyze our architecture has increased a dozen fold. How
you manage your variable declarations will directly impact your overall memory utilization, as well as assist you
in preventing race conditions within your app. The <em>let</em> and <em>const</em> declarations really fine tune
that control.
The <em>let</em> declaration construct is fairly straightforward. It is a block level scoping mechanism,
supplanting <em>var</em> usage in most situations, and controls the "this" level access of those variables.
The <em>var</em> declaration construct was a function level scope. What's the difference between block level
scoping and function level scoping? Consider the following:
<code>
for (var i = 0; i < 10; i++) {
console.log('i = ', i);
}
console.log('now we are outside of our block. i = ', i); // i now equals 10
</code>
Function level scoping means that variables declared using the <em>var</em> construct are available only
within the confines of that function, but are not restricted to the block they are declared within. Running
the above example shows you that <strong>i</strong> still exists outside of the for loop block. What happens
though if we change that declaration to a block level declaration?
<code>
for (let i = 0; i < 10; i++) {
console.log('i = ', i);
}
console.log('now we are outside of our block. i = ', i); // throws an error that i doesn't exist
</code>
In the case above, the variable <strong>i</strong> is now a block scoped variable and, as such, is <strong>only</strong>
available within the confines of the for loop. The variable is cleared from memory once execution is complete
(since there are no references created to those variables in the block), and their values are not available
outside of the block, reducing the opportunity for race conditions.
Probably the most misunderstood of these constructs is the <em>const</em> form of variable declaration. Most
still think of this as setting an immutable <strong>constant</strong>, but that's not entirely correct. Let me give
you an example:
<code>
const myVar = 'JavaScript is really ECMAScript';
console.log(myVar.replace('really ', ''));
myVar = 'Purple Haze'; // This throws an error, because you can't do this
</code>
OK, that example supports that whole "immutable constant" kinda thing. But that isn't the whole story. Let's
look at another example:
<code>
const myVar = {};
myVar.foo = 'bar';
console.log(myVar.foo);
myVar = {}; // You were just fine til you got to this line
</code>
"Wait? What?" Yes, you can change a variable declared with <em>const</em>. Sorta.
When you set a variable with <em>const</em>, you are assigning a variable to a specific location in memory.
It is set to the type you initially assign. You can adjust properties of that variable, but you can not replace
the variable, even with one of the same type. This is why examples with a simple type (string or numeric or
boolean) would throw an error, but you could create and remove and adjust object keys or array elements all day
long. The variable itself isn't <em>constant</em>, it's location in memory is.
Which allows me to change an example from a <a href="http://www.cutterscrossing.com/index.cfm/2015/11/16/Angular-Data-and-ES2015-Classes">
previous post</a>. In that post, I talked about using implicit ES2015 getters and setters, and showed an example
of broadcasting a variable change in a service from within a custom setter method. I had a variable in my
Controller that was not passed in to the Service by reference, so any time I changed the Service variable it had
to broadcast that change to my Controller so I could update the controller level variable. In my original example,
the variable was originally assigned to the class' "this" scope. But with <em>const</em> I can assign that variable
and hold it's location in memory, thereby passing the memory reference and changing how I can control workflow.
<code>
'use strict';
class MyController {
constructor ($scope, dataService, orderService) {
this.$scope = $scope;
this._dataSvc = dataService;
this._orderSvc = orderService;
const myCrazyVar = {};
// setting to 'this' too, for controller public accessable reference
dataService.myCrazyVar = this.myCrazyVar = myCrazyVar;
}
}
myController.$inject = ['$scope', 'dataService', 'orderService'];
export {MyController};
</code>
<code>
'use strict';
class DataService {
constructor () {
this.myCrazyVar = null;
}
}
export {DataService};
</code>
<code>
'use strict';
class OrderService {
constructor (dataService) {
this._dataSvc = dataService;
}
add (order) {
// update our shared data
this._dataSvc.myCrazyVar.orderid = order.id;
}
}
orderService.$inject = ['dataService'];
export {OrderService};
</code>
Is this wise? I'm sure if you aren't careful you can create issues. But, by passing that memory reference
around you also eliminate the need to duplicate variables and broadcast events unnecessarily, reducing your memory
footprint and cpu utilization.
Learning when to use <em>let</em> and when to use <em>const</em> will take some time for many who've worked
with JavaScript for any length of time. I'm sure this will be one of those new features that takes some significant
time to gain true traction among developers. In the end run, it will force us all to think ahead about the
architecture of our applications in advance (always a good thing), and the impact of our code on performance.
Now, if I can just convince Ben ;)
DevelopmentES2015JavaScriptWed, 18 Nov 2015 10:27:00 -0000https://www.cutterscrossing.com/index.cfm/2015/11/18/Death-to-Var--Why-Let-and-Const-Really-Interest-Me-In-JavaScriptAngular, Data, and ES2015 Classeshttps://www.cutterscrossing.com/index.cfm/2015/11/16/Angular-Data-and-ES2015-Classes
I'm really loving the changes introduced in ES2015 (otherwise known as ES6 or
the new JavaScript). At work we've transitioned to working in ES2015, and discovering
the differences has been both fun and challenging, especially when it comes to
changes in how variables are scoped. But we'll save some of that for another
day, and talk for a moment about passing data around in an Angular application,
and how you can have some fun with ES2015 classes.
In Angular, a Controller can have Services as dependencies. Services are singleton
in nature, so a Service shared among multiple components can be used to "share"
data, to a degree. First, let's create a simple controller with a few dependencies
and a custom variable we want to track both within the controller, and among
other bits of the app.
<code>
'use strict';
class MyController {
constructor ($scope, dataService, orderService) {
this.$scope = $scope;
this._dataSvc = dataService;
this._orderSvc = orderService;
this.myCrazyVar = null;
dataService.myCrazyVar = this.myCrazyVar;
}
}
myController.$inject = ['$scope', 'dataService', 'orderService'];
export {MyController};
</code>
Next, let's create some simple method in the <em>orderService</em> that needs
access to our custom variable. We can easily do this with the shared dataService:
<code>
'use strict';
class OrderService {
constructor (dataService) {
this._dataSvc = dataService;
}
add (order) {
// get our custom var for quick reference
let forNow = this._dataSvc.myCrazyVar;
// do a bunch of stuff, then
forNow.OrderId = order.id;
// give our changes back to our dataService
this._dataSvc.myCrazyVar = forNow;
}
}
orderService.$inject = ['dataService'];
export {OrderService};
</code>
First, some might ask "Cutter, why didn't you just pass that variable into the
method?" Well, sometimes you just can't. Others might ask "Isn't it passed by
reference?" Scoping changes have adjusted how this works as well. Changing the
variable in the service won't automatically update your controller variable. We'll
talk more about that in a moment. Still other's might ask "What is 'let'?"
That's a conversation about the differences in variable assignment in ES2015, and
is really a discussion for another day. Ultimately I used <em>let</em> because
I need the variable to be mutable.
But, to explain what I'm doing here, the <em>add()</em> method takes an order.
What you can see of the method, it gets our custom variable and applies it to
a local variable for easy reference. We update it with data from the <em>order</em>
that was passed in. We then reset the Service property with the updated data.
OK, but that syntax with the Service property is odd, coming off of ES5. How
does that work? Well, ES2015 classes allow for implicit getters and setters of
properties. Consider the following:
<code>
'use strict';
class DataService {
constructor () {
this.myCrazyVar = null;
}
}
export {DataService};
</code>
In the past, to access and change a property of an object would have required
us to write some kind of getter or setter method. In this example, you can
simply access and change the property directly through dot notation. But let's
say you want to do something a bit more complex. There may be some bit of pre-
or post-process you want to do, either when setting or getting the variable.
For this, ES2015 classes allow you to define custom getters and setters:
<code>
'use strict';
class DataService {
constructor () {
this._myCrazyVar = null;
}
set myCrazyVar (value) {
// I can do what I want in here
this._myCrazyVar = value;
}
get myCrazyVar () {
// I could do stuff here too, if I wanted
return this._myCrazyVar;
}
}
export {DataService};
</code>
Where this could come in handy is in that inter-app communication. A Controller
can call methods on the Service, to set values and stuff, but the Service can't
automatically pass data back to the Controller based on actions from other items
accessing the Service (like our orderService interaction above). But, in Angular,
we can use event handling and binding in this instance. First, let's put a listener
on our controller:
<code>
constructor ($scope, dataService, orderService) {
this.$scope = $scope;
this._dataSvc = dataService;
this._orderSvc = orderService;
this.myCrazyVar = null;
this._dataSvc.myCrazyVar = this.myCrazyVar;
$scope.$on('crazyUpdated', ($event, newValue) => this.myCrazyVar = newValue);
}
</code>
Yes, the arrow function is a different concept for most front-end-only developers. I'm
not going in depth on that here, but you can find plenty of info out there about them. The
gist here is that if the <em>crazyUpdated</em> event is cast it will pass a new
value, that we then use to update the Controller variable. This also tells us
that <em>myCrazyVar</em> will always be changed from outside of the Controller.
Now let's do some magic to make sure that event gets cast. In our <em>dataService</em>:
<code>
'use strict';
class DataService {
constructor ($rootScope) {
this._myCrazyVar = null;
}
set myCrazyVar (value) {
this._myCrazyVar = value;
$rootScope.$broadcast('crazyUpdated', value);
}
get myCrazyVar () {
// I could do stuff here too, if I wanted
return this._myCrazyVar;
}
}
DataService.$inject = ['$rootScope'];
export {DataService};
</code>
So we use our custom property setter. When the value is changed, it automatically
broadcasts that change. The Controller then picks up that change, and applies it
to it's own internal variable.
So, what have we learned here? Well, first there's some samples on using ES2015
classes as Controllers and Services within Angular. Simple examples, but there
you go. Next, we talked about class property getters and setters, both implicit
(no need to define, they just work), and explicit. Our explicit example shows
where you can apply some additional logic during those processes. This may not
be the greatest example, but it shows you that you can do stuff. Probably the
greatest usages here will be in data validation, or in splitting concatenated
data (like a full name to first and last, for example).
Using those ES6 classes in your app is a matter of <em>import</em>ing the
classes into your app:
<code>
import {MyController} from './MyController';
import {DataService} from './DataService';
import {OrderService} from './OrderService';
// ... other app init stuff
.controller('MyController', MyController)
.service('dataService', DataService)
.service('orderService', OrderService);
</code>
So, it's still all new to me, these changes to scope and classes and the like.
But it's fun, and powerful, and has a ton of possibilities. If I screwed something
up just let me know. All feedback is welcome.
DevelopmentAngularJSES2015JavaScriptMon, 16 Nov 2015 10:48:00 -0000https://www.cutterscrossing.com/index.cfm/2015/11/16/Angular-Data-and-ES2015-Classes