Fun with AngularJS Directives, Isolate Scope and two-way binding

I have a directive defining a component that is reused in a number of views.

I have a view in my app that needs 2 instances of this component.  I also need the two instances to be in sync and behave as one.*

In order to create this illusion, I have defined an object in my view’s controller that will hold the pieces of data needed for the two instances of the component to be able to appear as a single entity.  I pass that object to the directive’s isolate scope with**:

scope: {
  data: '='
}

My component has a couple of functions that manipulate the data object.  These work as expected. I can add and remove properties with the object and both components backed by the object behave as I would expect.

One piece of functionality of this component is CLEARING all of the properties that have been added to the data object.

Of course, the fastest, easiest, and most efficient way to clear the data object is to simply assign an empty object:

$scope.clear = function() {
   $scope.data = {}
}

The alternative of iterating through each key and removing it is obviously not as amazingly time-efficient.

HOWEVER, the two-way binding does NOT work with this assignment.

I repeat: DOES NOT

  1. Adding a property (name: ‘bob’) to the data object
    In the console, I pause the debugger in BOTH the component.js and the controller.js to find that each time $scope.data is the following value:

    { name: 'bob' }
  2. After running in clear(), in the console, I pause the debugger in the component.js and it reports that $scope.data is the following value:
    {}
  3. However, pausing the debugger in controller.js reports that $scope.data is the following value:
    { name: 'bob' }

 

My first thought was “Of course! The isolate scope must have an address it’s watching that was updated when I assigned {} and the controller’s scope did not get that memo and is still looking at an old addy”

Is that true?

I’m not sure. The jury is still out and research is still being done (should you have a definitive answer I’d love to hear it)

Meanwhile, here’s some EXCELLENT info I found on Isolate Scope in Angular:

  1. Isolate-Scope Two-Way Binding is not simply an object reference. The magic is created through angular’s $watch functionality and is *eventually* consistent
    https://www.bennadel.com/blog/2726-isolate-scope-two-way-data-binding-is-eventually-consistent-in-angularjs.htm
  2. $watch() and $watchCollection differences:
    https://www.bennadel.com/blog/2566-scope-watch-vs-watchcollection-in-angularjs.htm
    I was a bit surprised the “rebuild” worked in all cases. I thought perhaps that would clearly define why my situation occurred, but I do not think so after watching that demo.

*Decisions made over two years ago and new designs without the time for a complete refactor gave birth to this situation in the first place.
**This example was simplified

Advertisements

Locally running SquareSpace

squarespace

What is SquareSpace?

Squarespace is a content management system that enables users with little to no technical experience easily build, manage and host a website or blog.

If the default templates and behavior isn’t quite what you’re looking for, the platform offers “Developer Mode.” Turning this mode on for your site allows you to write custom templates and code snippets to modify your site’s default look, feel and behavior.

Tip: If you turn OFF developer mode, all that custom code disappears into the aether.  More about that here.

Why run locally?

As anyone with development experience knows, changes don’t always look or behave as planned and bugs happen.  To remove the risk of deploying a change that could break your site (or your client’s site) during the development process, it’s great practice to develop those changes locally, test them, and then push them to your live site once you’re sure they’re production ready.

Getting Setup

Install the Prerequisites:

  1. Install Git (Guide)
    New to git? Checkout this primer.
  2. Install Node Package Manager (NPM) (Guide)

Install the SquareSpace Developer Platform:

While I found there to a few more steps (listed below), the official SquareSpace Guide is just the right place to start after you have your prerequisites installed.  Check it out here: https://developers.squarespace.com/local-development/

Finishing the Setup (The stuff the guides don’t tell you)

Site Name

If you follow the directions linked above verbatim, at the end of it you might find you have this:Screen Shot 2016-08-31 at 12.52.25 PMThis means you still need to update your template.conf with your site name. In this example, I am using the domain name demotesttest.squarespace.com.  When you open template.conf you’ll find that it doesn’t yet have a server section.  You’ll need to add a server property and within it add the siteURL property/value to the object.

    "server": {
        "siteUrl": "https://demotesttest.squarespace.com"
    }

Add the above snippet (updating for your site’s actual name) to template.conf
Tip: Don’t forget the comma before and/or after the server section.  See the full template.conf below for more help.

What is my site’s name? How do I change it?

You can view and change your site’s name on Squarespace.com by navigating to
Settings -> Domains.
Recommendation: You might want to make your site’s name something a bit easier to remember than the auto-generated name.
More Information here: https://support.squarespace.com/hc/en-us/articles/206541717

Authentication

After updating your template.conf and restarting the SquareSpace server, you might find yourself staring at a message like this one:

Screen Shot 2016-08-31 at 1.09.54 PM

SquareSpace essentially wants to pull down and cache everything from your live site to run it locally and to do to that it needs permission to get at your git repo.

So your new login command should be:

squarespace-server https://demotesttest.squarespace.com --run-authenticated

After the server starts up, it will prompt you for your SquareSpace email and SquareSpace password:

Starting DevelopmentServer

           _
       /  /      _
      /  /  /  /   \
     /  /  /  /  /  |    Squarespace Inc.
    |  /  /  /  /  /     Local Development Environment
     \ _ /  /  /  /
              /  /
            -

Version 0.4.5
Squarespace email: <your squarespace email>
Squarespace password: <your squarespace password>

Style’s not loading?

Opening http://localhost:9000 in your browser should have all your content.  I found if you followed along with the setup from the basic template, you might find all your content is there and none of your styles.

I found that the base style needs to be explicitly listed in the template.conf when running locally.  To do that ,we’ll add base.less to the stylesheets array in template.conf.

Open template.conf, find the stylesheets section and add base.less to the array:

"stylesheets":[
    "base.less"
   ],

Voilá

This time when you start your server, everything should be loading as expected.

You’re all set to begin development: alter code and refresh your browser to view the updates (you do not need to continually quit & restart your server to see changes).

Once your local changes are ready for prime time, you have to use git to commit them and push them up. (Git Primer)

Happy Coding!

Full Template.conf:

{
   "name":"Developer Platform Beginner Tutorial",
   "author":"Squarespace",
   "navigations":[
      {
         "title":"Main Navigation",
         "name":"mainNav"
      }
   ],
   "layouts":{
      "default":{
         "name":"Default",
         "regions":[
            "site"
         ]
      }
   },
   "stylesheets":[
    "base.less"
   ],
    "server": {
        "siteUrl": "https://demotesttest.squarespace.com"
    }
}

And in Swift we call, “Guards!”

guards.jpg

A quick blurb on a nifty feature I came across today in the Swift Programming Language Guide:

guard statement

I guard against invalid values ALL the time with a nice little if/else statement upon entering a block of code, but here swift has made an even more readable keyword to highlight the behavior: guard

The guard statement functions just like a if statement: it checks for a boolean value of some conditional statement.  But unlike an if statement, guard statements MUST have an else clause and that else clause MUST exit the code block within which the guard statement was executing.  Written another way: if your conditional fails the guard check, you get tossed out of the code block.  How you get thrown out is up to you: return, break, continue or throw are all legit reactions.

Additional bonus behavior, any variables or constants assigned using an optional binding during the evaluation of the guard conditional are yours to keep throughout the block within which the guard exists.  What I mean here is, lets say enter a function and in your first line, you assigned a value to a variable in the guard statement such as:

guard let puppy = pet.name { …. }

And the guard statement evaluated to true, you could later reference puppy elsewhere in the function.

Note: I’m looking forward to using some guard statements instead of if/else just to be cool.

What Every Beginner Should Know About Learning to Code

I’ve been teaching introductory coding classes for Girl Develop It Austin for over five years.  In that time, I have had the opportunity to work with students from a wide variety of backgrounds (stay at home moms, communications majors, artists, database admins, etc.) and have been privy to a lot of different reactions to learning how to code not least of all include moments of fear and frustration.

laptopAll beginning developer classes should start with a brief discussion about the expectations the students have regarding how this journey is going to go.  I’m talking about the expectations they’ve set on themselves.  My typical student has an extremely high expectation of herself– expectations caused by not knowing how the average developer has learned how to code.   It doesn’t hurt to tell them of your own missteps and opportunities for growth (that’s what we’re call “mistakes” here!).

My experience as an instructor and TA has taught me that students have a much more pleasant and successful experience if they begin knowing these five rules:

  1. Things are going to Break
    It’s ok.
    Fixing broken things is the MOST important part of learning how to code.  I can’t tell you how many things I’ve learned because I had to fix them after I broke them.
  2. Breaking things is a sign of Intelligence
    We have a rule at my company: If you don’t break production, you’re not really doing anything important.  You can avoid breaking things if you copy/paste solution code in a class, but what are you learning aside from a copy/paste shortcut? People who get curious and try something new have to follow rule 1. It’s probably not going to work the first time, but you’ll learn how to make it work or worst case: you learn why it won’t.
  3. You’ll probably need a cheatsheet.
    Think back to grade school. When your teacher gave you a vocabulary list, did you immediately remember and know how or when to use all of the words? Probably not. I’ve seen a number of students get frustrated because they can’t remember all the keywords instantly after being introduced to them, and the deal is: no one expects you to.  It’s ok (and expected) to have to look it up (even multiple times). I know I still do.
  4. The language is only part of it
    Despite knowing how to construct a perfect sentence in English, not all the sentences you ever write are going to turn into a bestselling novel.  Learning a programming language is the same; instead of epic novels, we’re trying to write amazing programs.  They come with time, practice and a bit of trial and error.
  5. Build
    When you build something for yourself you’ll find the motivation to push through barriers.  To make your vision come true, you’re going to run into things you haven’t tried before, but because it’s your vision, you’ll learn what you need to in order to make it become a reality.

I hope to leave all my students feeling that the world has gotten a bit bigger and the new space they can play in is welcoming, inviting, and exciting.  I love to code and I want to share that with all of them.  I want them to dream big and then set on the journey to make their big dreams come true despite knowing that the whole thing is going to be littered with the obstacle “I don’t know how to do that” and that obstacle is the best fuel for learning more.

Swiftly picking up iOS Development

From a few JavaScript frameworks, Java and a little bit of Android programming to Swift…

I’ve  technically written in a number of programming languages thanks to numerous CS courses that insisted I be exposed to the nuances of different code, but I’ve spent most of time as a professional developer writing in JavaScript and/or Java.

Instead of stubbornly bumping over the pot holes on the road to swift proficiency, I decided I’d fill in the gaps of my knowledge with a little swift primer.  Below you’ll find my cheatsheet of takeaways for the OOP (but not yet swift) programmer:

Variables

Constants & Not

Variables in swift (like in Java) come in immutable and mutable varieties specified with the following keywords:

  • constant (immutable) use the keyword let
    let pi = 3.14
  • variable (mutable) use keyword var
    var nickname = "Ash Attack"
Types

Swift can use type inference to infer the type based on the initial value, but unlike the loosely typed free for all that is Javascript in swift once a type is set it cannot be changed.

If you want to specify a type, you write it after the variable name separated by a colon:

let pi : Double
Optionals

Optionals are variables that could have a value or could be nil (null is out we’ll have to start saying “nil” now).  To use an optional, you have to unwrap it.  To implicitly unwrap an optional, you use “!” which is fine as long as you know the optional will always have a value after initialization (e.g. outlets connecting the UI & source code).

Flow Control

If Where?

The first time I saw this syntax I felt that the programming language and mySQL had a baby.  Let’s say I really only like puppies whose names begin with I:

var puppy:String? = "Ivy"
if let pupNameTag = puppy where puppy!.hasPrefix("I") {
   greeting = "Hello \(pupNameTag)"
}

If puppy doesn’t have the prefix “I”, the variable pupNameTag is nil and the if statement fails to execute the code block and the people-for-puppy-egos descends upon me as I have become some rude person who doesn’t say hi to the adorable puppy.

The code above also shows the format for String Interpolation.  I found the following behavior a bit strange: if I want to print an optional’s value with the String Interpolation format the output of “String Interpolations with Optional \(optVal)” where var OptVal:String? = “bob”  (notice the “?” declaring this an optional) prints out

String Interpolations with Optional(bob)

I’m sure that’s going to surprise me someday.

Range Operator

A couple new operators for me

The half-open range operator:

..<

for i in 0..<4 { }

Essentially the following in Java

for (int i = 0; i<4; i++)

And the close range operator (aka inclusive)

for i in 0...4

Essentially the following in Java

for (int i = 0; i<=4; i++)

And apparently, the swift folks have decided that there’s no reason for there to even be an ‘i’ if we don’t need it in the loop (I do teach intro to programming classes and you’d be surprised how many people have a thing against the ‘i’).  They have provided us with an underscore as a wild card so this works:

var count:int = 0
for _ in 0...4 {
   count++
}

And when we’re done, the value of count is 5.

Functions & Methods

The syntax notes:

  1. The keyword func declares a function
  2. name:type is the parameters list format
  3. -> ReturnType 
func aFunction(name:string)->Int { 
   // Do Stuff
}

A special note (which in hindsight made the first tutorial I went through make so much more sense): When calling a function you list the first parameter without its name and every other one in the format name:value

Lingo Alert:

Functions defined within a specific type are called methods and are called with the dot syntax

Classes, Initializers, Inheritance

Initializers Aka “Constructors”

Because we can’t keep it uniform to what we just learned about Functions:
When you call an initializer all parameters are in the name:value format

There are a few different terms and types of initializers in Swift:

failable initializer – An initializer that can return nil after initialization if the parameter values that are supplied are tested and out of a desired scope

Designated Initializer – A “primary initializer” any initialization chain must ultimately call a designated initailizer.

Convenience Initializer – Most likely will call on a designated initializer supplying default values for parameters not required when calling the convenience initializer itself but still needed to initialize an instance of the object.

Class & Inheritance

Required – A keyword that’s used to declare every subclass with the “required” initializer must implement its own version

Classes are declared with the following syntax:

class SubClass:SuperClass {
   // Be cool
}

Similarly to that @Override notation in Java, Swift has an override keyword that you can use when overriding a superclass function

override func name()->returnType

Enums & Structs

We have enums in Java and I’m familiar with Structs from the ancient times when I wrote C code, but I noted the syntax for declaration:

enum Name:rawValueType

Unlike C enums in swift each case in the enum does NOT require an correlating int value.  However, if you do have a raw value you can declare so as shown above.

Note: Structs in Swift are similar to classes.  They have methods and initializers but are passed by copying while classes are passed by reference.

Protocols

Basically an Interface

Lingo Alert:

Protocols are adopted by a class, struct or enum.

Any class, struct, or enum that “implements” a protocol is said to conform to the protocol.

get – a keyword to specify that a property is read only:

var readMe:String { get }

To declare you are conforming to a protocol list it after any super classes in the class declaration:

class SubClass:SuperClass Protocol {
   // I implement all the protocols
}

Conclusion

I suspect typing this up will be most helpful for: me, and after writing a bit more code, I won’t even be able to remember a time when this wasn’t second nature.  But on the off chance this serves as a launch pad for other JS/Java Devs wanting to swiftly dive in to iOS development without having to sift through programming basics to find the gold nuggets that’ll make that swift code blurb you’re staring at look like plain text– Enjoy!

This is your very first post. Click the Edit link to modify or delete it, or start a new post. If you like, use this post to tell readers why you started this blog and what you plan to do with it.