Tag Archives: JavaScript

AngularJS Single Page Application – To do List Part II

When we last left, our intrepid developer in the making, he had had completed the shell and basic setup of his AngularJS app. Lets see what he’s upto this week…

The To do list has so far taken shape and the basic structure and logic was coded. However adding an item presented two issues:

  1.  We couldn’t add more than one item
  2.  The added item was bound to the new input field

Issue ‘1’ turned out to be Angular pointing out that the ngRepeat directive does not allow duplicates – the message could be seen in the console.

Angular error: Duplicates in repeater are not allowed.

This happens when there are duplicate keys in an ngRepeat expression. Also not having any key implies all items have the same key – food for thought. The resolution is adding  ‘track by $index’ to the ngRepeat attribute value

ng-repeat="item in item track by $index"

This assigns each list item a key by virtue of its index where there is no explicit key defined. This fixes issue ‘1’ and more items can be added to the model, however all of those added items are all bound together and in turn to the input box. So every time the value is updated, all instances are updated as well. [see commit]

After scouring the interwebs for a bit and running through a few related but not similar issues on stackoverflow and old old tutorials, I tried a few things

  • Changing the array of objects to just an array of strings [not much different but when you’re going crazy and it’s nearly bed time might as well]
  • Tried using different versions of angular [static library was used, an old version 1.2.16, then the latest and something in between]

Finally what worked was not passing in the new object created using the ngModel directive as a parameter in the ngClick directive on the button and then getting the object from the $scope directly within the add function call.

Before:

<input type=text ng-model=new.name/>
<button type=submit ng-click=add(new)>Add</button>$scope.add = function(item){
$scope.items.push(item);
…}

After:

<input type=text ng-model=new/>
<button type=submit ng-click=add()>Add</button>$scope.add = function(){
$scope.items.push($scope.new);
…}

Not entirely certain why it was fixed, but assuming that somehow accessing the object from the $scope ensures that each one is separate from the others and doesn’t end up being tied to the same instance as before.

For now it’s doing another aspect of what we intended to do – adding items to the list correctly without duplication.

I’ve pushed the changes [see commit] and added a github page to see it in action – To Do App

 

AngularJS Single Page Application (SPA) – To do List (Part I)

So as outlined in my previous post AngularJS Single Page Application (SPA), I’ve started working on the bare bones (first commit) of the To do list app – so little that a Hello World tutorial would have had more moving parts [Zing].

I’ve started fleshing out the AngularJS aspects, particularly the module, controller and associated data holder (an array) and a function to add to that array (fingers crossed).

So far it’s not working. I pre-populated the array with an object literal containing a ‘Sample Item’ value in the hopes that it will render in the expression statement {{ }}. But nada. Some things I thought was the cause:

  • I’d placed all of the script tags at the bottom of the HTML page, so it would load only after the DOM was rendered. [moved it up]
  • I’d referred to the angular.js file in script tags and within those tags placed all the code. [moved the code to its own script tag]

So still trying to figure out why AngularJS isn’t initializing.

[UPDATE] Ok so turns out I missed the ngApp directive, woops¯\_(ツ)_/¯, which meant that it was just a plain old HTML file with odd little tags which mean nothing and displayed the double curlies as just content – {{ item.name }}.

With that done, I was able to get the array with the pre-populated object literal to appear and and… the ability to add a new item (One of the most main functions on a to do list). Unfortunately, the new input box is bound to the previously added item – it updates when you type in another item and can’t seem to add anything further.

Check out the code [ commit ] until now and stay tuned as I go scratch my head some.

Hoisting in JavaScript

Everyone’s heard the all too familiar, JavaScript is an interpreted language spiel. That’s only partly true. Certain instances  can catch unwary developers out about this idiosyncratic run-time behaviour.

When a JavaScript engine parses a code file, a global execution environment called the execution context is created. This occurs before the file is executed where functions, variables etcetera are ‘hoisted’ into memory. Think of this as instantiation in other languages.

Hoisting is what allows function calls, which occur before the function definition, to run without throwing an error – as the entire function will be hoisted to memory.

This causes issues where function expressions are used. Function expressions are anonymous functions which are assigned to a variable as opposed to a function statement:

// Function Statement
function doSomething(){
   console.log("something done");
}

// Calling 
functionHolder();

// Function Expression
var functionHolder = function() {
   console.log("doing something else");
}

In this case the variable functionHolder will be hoisted into memory, however it will be ‘undefined’ until the interpreter reaches the actual line where the anonymous function is assigned. At this instance a function object is created and assigned to the variable functionHolder.

For more details about functions expressions, see:
the official description on MDN
JavaScript functions
JavaScript callback functions

JSON and JavaScript Objects

JavaScript Object Notation (JSON) is the lightweight alternative to tag laden XML used as data exchange format. What it is, precisely, is a method of data transmission based on JavaScript’s object literal syntax.

JavaScript objects are containers which store key value pairs of attributes, functions and other objects of the following appearance:

var anObject = {
 firstProperty: 'someString',
 secondProperty: 111,
 aFunc: (parameter) {
         // some code
     };
 isJSON: false
}

JSON follows the same exact pattern:

{
  "firstProp": "someString",
  "secondProp": 222,
  "isJSON": true
}

Few items of note that distinguish between JSON and plain old JavaScript objects:

  • JSON requires that properties by enclosed in quotes, while JS Objects can do it either way.
  • JSON only contains key value pairs, no functions

Back and forth

Although not part of the language, its ubiquity means that JavaScript has helper methods to handle JSON. Most common function is to convert from an object literal to JSON and vice versa:

///////////////////////////////
// Object literal to JSON
///////////////////////////////
var myObject = {
   firstProp: "someString",
   secondProp: 222
}

var JSONresult = JSON.stringify(myObject); 
// Result
//  {"firstProp": "someString", "secondProp": 222 }

///////////////////////////////
// JSON to Object literal 
///////////////////////////////
JSON.parse(JSONResult);
// result
// { firstProp: "someString", secondProp: 222 }

So although similar, JS objects and JSON are not the same. In essence JS objects is how you might be normally at home, relaxed and casual versus while JSON is like being in public with more formalised rules.