Tag Archives: SPA

AngularJS To do App – Part IV

Following from the previous entry, there was just one feature remaining for the rudimentary functionalities of our app:

  • Check of an item

I added an input checkbox to the ngRepeat construct. And after some fumbling around and going through some forums + angularjs developer documentation, I managed to apply a simple class styling to the item in the list when the checkbox is checked.

// Class applied when model ticked is true
<input type="checkbox" name="tickbox" ng-model="ticked" />
<span ng-class="{'checked': ticked}"> {{ item }} </span>

// CSS style that's applied
.checked {
text-decoration:line-through;
color: gainsboro;
}

This accomplishes a somewhat crude implementation of a To Do list item being checked off. However, the styling seems to fall through to the next item when a checked item is deleted. Also a checked item should preferably be locked from being edited.

So that still needs to be worked on and possibly some extra refactoring of the code in terms of button states as extra conditions required to prevent the fall through will only add to the growing list of conditions on some of the buttons already:

<button type="submit" ng-show="updateShow" ng-click="update($index, editedItem); updateShow= false; showEditInput = false; editShow = true;">Update</button>

Apart from that some aesthetic tweaks to the design and form is warranted. So stay tuned and check out the latest:

App – To Do | Commit

AngularJS To do App – Part III

So out of the remaining features, what should I pick next to work on, hmm let me see. Edit an item, sure why not. Why not indeed.

  • Check of an item
  • Edit an item
  • Delete an item

It turned out more difficult than I had (not) anticipated. Not the most crucial feature but sure. Thought it would take a few days to figure out and slow down development as I couldn’t find much of a guide from scouring through a book or two and several forums.

Thought there might be some directive floating around I could use (didn’t find anything remotely close). Then I tried to do a simple update the array item in place technique.

But therein lay the difficulty as threading it through AngularJS wasn’t easy going. I cycled through a few ways to do it. Some of it involved  a straight ngClick using the $index as a parameter which would try and update the array item based on that index.

That didn’t work as the button I wired up to do the ‘in place’ editing simply cleared the value already present and just left the input field and buttons showing:

$scope.update = function(index){
  $scope.items[index] = $scope.item;
}

Or something along those lines as I’d changed code and banged my head so many times I can’t quite remember.

It did work eventually by recreating the first pattern I had for adding an item into the list – I needed to create a new model on the fly using ngModel and then passing the $index and that model to the function call within the controller code. Still peculiar how I couldn’t get it to work by referring to the newly created model from the $scope variable.

In hindsight the solution I came up with is very very simple and it works. The condition updating to show/hide buttons for editing purposes is verbose. Hopefully find a more succinct system or pattern online later for refactoring but for now it does the trick.

So now just one primary function left to complete to call it a mvp

  • Check of an item

For now here’s the updated demo To Do App & the latest commit.

AngularJS To do App – Part III

So continuing on and upwards, what every To do list should have, in no particular order are the following:

  • Check of an item
  • Edit an item
  • Delete an item

Incidentally the first thing that came to mind was the delete function (only when I had that did the rest occur, which arguably are more important features).

I somewhat implemented deleting by including a  button with a ngClick directive within the ngRepeat directive:

$scope.del = function() { $scope.items.pop(); }
<ul ng-repeat="items in items track by $index">
<li>{{ item }} <button type="submit" ng-click="del()">X</button></li>
</ul>

Sure, it should only affect the item it is (magically) tied to heh, heh… no. Pop didn’t go the weasel as it removes an array item from the end. And any other array method I’d come across didn’t seem to be able to remove items unless at the start or end. However, in that same post I had linked to ECMA-262 (Standards Document) which is the comprehensive language specification guide for ECMAScript, or JavaScript as its known as when not protecting Gotham city. That had fairly detailed (verbose) items about array methods – in particular Array.prototype.splice. I thought it was like slice but it seems similar to what a delete function should do:

Array.prototype.splice (start, deleteCount, ...items )
Note:  When the splice method is called with two or more arguments, start, 
deleteCount and zero or more items, the deleteCount elements of the array 
starting at integer index start are replaced by the arguments items. 
An Array object containing the deleted elements (if any) is returned.

Sounds about right, except I don’t want to want to replace anything with something else, nor return the deleted item. The language specification document is not the most user friendliest nor have any usable examples, but there’s tons of other information available on splice online.

W3schools.com states that the splice method adds AND removes items (holy utility belt stuffer Batman). Also it clearly states that second and third parameters are optional.

So our delete function is pretty similar to the add function:

$scope.del = function(index) { // parameter for index
  // start at index required and delete one item, which is itself
  $scope.items.splice(index, 1);
}

So in our HTML, we just need to just latch onto current index position of the item to which the delete button (with the ngClick directive which is iteratively assigned by ngRepeat) is attached.

Being the cool cat I am, I intuitively (counter it seems in hindsight) just threw in ‘this’ into the delete function as a parameter

...ng-click="del(this)">...

Because this is all powerful, this is better than that (except when you assign this to that). I should’ve known better than that – what I did was a total party foul, which I won’t get into at this moment. At that stage the list item was being removed from the top, like shift() would. The proper solution, it turns out, was staring at me all along.

I ran into the issue of not being able to create more than one item in the list, mentioned in the previous post, because AngularJS doesn’t like duplicates in the ngRepeat directive. The fix was add ‘track by $index’ – which assigns, and I quote, “each list item a key by virtue of its index…”

So now each added item has its own delete button which only applies to that item.

All the updates can be seen in the latest commit.
Updated functionality can be seen on the associated github page ‘ToDo’. (might need to do a hard refresh to get the latest working example).

More on the other features coming shortly…

ps I renamed my html file from ‘todo.html’ to ‘index.html’ which shows up in github diff as two different pages.

AngularJS To do App – 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 To do App – 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.

AngularJS Single Page Application (SPA)

So for my next quest, I’ve decided to go with a Single Page Application for the following reasons:

  • To start exploring JavaScript frameworks
  • Get some much needed interactivity on screen
  • Increase the complexity of the projects I am going after to move out of my comfort zone

I’ve decided to test the water with AngularJS. Why you might be asking? Well the previous mini project I completed was using PHP, and to further build on that language I chanced upon a course on pluralsight Building a Site with AngularJS and PHP. Since tacit conditions mean I can’t write about non JavaScript related builds, it made sense to do a crossover. Granted, I doubt I will be using a PHP/AngularJS combo for what entails.

The pluralsight tutorial was interesting but the nature of tutorial videos and instructor bias of students understanding and assimilating information at the same level as they proffer the instructions, means that certain aspects would be glossed over with the student being none the wiser.

So, in keeping with the familiar thread throughout my journey, one of the best ways to learn is to attempt to build something yourself. And after much head scratching the best thing I could think of doing was a simple to do list. Yes partly because I have been drawing blanks and the fact of using something I have almost no clue about is daunting to say the least. Also this is a priming exercise to test the waters, so something overly complex isn’t the end goal.

So I shall start with the minimal of outlays and setups and progress from there as usual. Check out my ‘awesome’ concept sketch. Mind blowingly simple.

To do list concept sketch

Caveat: AngularJS is the first version that was released with Angular 2 onwards being a complete rewrite of the framework. So pursuing AngularJS is pure curiousity and what’s transferable to learning Angular2+ (currently Angular6 beta) might only be an exercise in comparative analysis.