Learning AngularJS – Part 2

As part of the series of posts that I’m planning to write about learning AngularJS, I’m going to write about each piece of significant functionality in the application.  I provided a brief explanation of the application in Learning AngularJS – The beginning.  In this post, I’m going to detail the search feature, explaining the way that I want it to work and what the problems that I encountered were.

I had decided early on that I wanted to place a search box and button on the header of each of my pages, mainly because of ease of use.  Partly because I wanted the user to be able to search from any point in the application.  I had originally looked at the Bootstrap Typeahead Component but keeping with the AngularJS theme, my next stop was Angular UI Bootstrap.  I had previously looked at these components for the work project that I was on.

In the module, I defined

var module = angular.module("mainIndex", ['ui.bootstrap']);

Specifying ui.bootstrap in the square brackets as part of the module declaration allows the Angular UI Bootstrap to be used,

The code to use the typeahead on the Index.cshtml is:

<div data-ng-controller="SearchController">
     <div class="form-group">
     <input type="text" 
               typeahead-on-select="setPerson($item.Id)"
               data-ng-model="selected" 
               placeholder="Personal Records" 
               typeahead="person as person.FirstName + ' ' + person.Surname for person in getPersonalRecords($viewValue) | filter:$viewValue"                                  typeahead-loading="loadingRecords" class="form-control">                                 
                 </div>                                                                                                                                                    <button class="btn btn-default" data-ng click="search()">Search</button>          
                 </div>

On the first div, there is a attribute value with the controller name defined.  I’m not sure whether I strictly need this as at the top of the index.cshtml page, I have an attribute, which tells me the AngularJS module to use.  The attribute is ng-controller but by adding “data-” you can stop the editor thinking ng-controller is a problem. By defining “data-“, the editor is tricked into thinking that this is a custom attribute.

The typeahead-on-select attribute allows the id of the person selected to be sent back to the controller.  The attribute data-ng-model should have performed this function too but I could not get the variable selected to pass a value across even with the $scope object injecting it.  The typeahead attribute specifies what the user will see like first name and surname and also called the function within the controller code to take what has been entered into the search box and contact the web api get method to return people.  The typeahead loading attribute will display the text or image specified.  The image up to now always goes slightly wrong for me.  That’s how I stuck with text.  Finally, I have a search button to take my selection and display it on a search results page.

Problems:

When I first added the typeahead input box I couldn’t get the person list to display at all.  This turned out be a flaw in the way that I returned the data to the page.  I was trying to add the data to $scope.person variable thinking that it would bind it and I could use person on the index page.  All that was needed was return result.data and the person list would display correctly.

My other issue was that when the user clicked search, the selected values were not be passed across.  The examples and posts were all favouring ng-model selected.  selected would then bind back to the controller providing it was specified.  I could never get this to work instead using typeahead-on-select, which used a function within the controller to pass back the value and assign it to variable.  Exactly the same way ng-model would but with more code.

The AngularJS controller itself is:

function SearchController($scope, $http, $log, $window) {

$scope.selected = '';
$scope.personal = [];
$scope.$log = $log;

$scope.getPersonalRecords = function (val) {
return $http.get('/api/People', {
params: {
searchTerm: val
}
}).then(function (res) {
return res.data;
});
};

$scope.setPerson = function (person) {
$scope.selectedPerson = person;
};

$scope.search = function () {
$log.log("Selected: " + $scope.selectedPerson)

$window.location = "Main#/searchPerson/" + $scope.selectedPerson;
}

The four parameters that are injected into the controller are $scope, which helps with the two way data binding, $http, which allows me to call the web api methods via a callback, $log, which is useful for outputting value and debugging through the code, and $window, which allows the controller to navigate away from the current view.

The first function gets the personal records using web api based on a search term that is entered by the user. For some reason, I have chosen to use a $http shortcut instead of using a data service that I have defined. I will speak more about the data service in later posts but that should change to dataService.getPeople(…) instead of $http.get(…).  When injecting the dataService into the controller the dollar ($) sign is not needed. The web api method will then return the result enabling the data to rendered on the page.

The second function setPerson is used to capture the id of the person selected after the search so that can be passed back to the search function further down. Opted for this way because I struggled to get ng-model to pass the value on its own. The input tag typeahead-on-select will then call the function, which sets selectedPerson variable.

The third function search takes the selected value and uses it to redirect the user to a search page.

I think that just about covers the basics of what I did. If there is anything that I’ve left out or could be done better, please do not hesitate to leave a message. Also sorry about the code examples formatting, just getting used to wordpress.

1 thought on “Learning AngularJS – Part 2

  1. Pingback: Learning AngularJS – Part 3 | The Inner Donkey Sanctuary

Leave a comment