Wiring Up citysearch
on the Home Screen
Now that we've got the citysearch
resource defined, let's try it out. In order to do that, we will need to alter the MainCtrl
Controller (in main.js
) and the main.html
template. We will set it up so that we use the existing text input and button on the home screen, but instead of immediately calling the current
resource, we will show the list of cities we have found so the user may select one.
Set up MainCtrl
in main.js
In order to search for cities on the home screen, we must use the citysearch
resource in the MainCtrl
Controller. We must also rework the way we assign variables and set up our refresh function. Here is what your MainCtrl
object should look like after you finish your edits:
angular.module('yourApp')
.controller('MainCtrl', function ($scope, citysearch) {
$scope.citiesFound = citysearch.find();
$scope.findCities = function(){
$scope.citiesFound = citysearch.find({
query: $scope.location
});
$scope.searchQuery = $scope.location;
};
});
You will notice that we are now using $scope
and citysearch
in this controller. We have create a $scope
variable called citiesFound
that we can use to loop through the results of our search. We initialize that value to the results of a default search. We also define a $scope
function called findCities()
, which performs a search and updates a $scope
variable called searchQuery
. This $scope.searchQuery
variable is an example of the kinds of variables you can use to improve the user interface. We will store the value of $scope.location
that we searched for so that we can provide good feedback to our user about the search results.
There is not too much code here, and for the most part it is not very different from the code we wrote to fetch the current weather. Hopefully these lines are starting to feel familiar and you're gaining some comfort with some of these common patterns.
Set up the main.html
template
Now that we have the MainCtrl
Controller all ready to power our view, we need to set up our template. This is also a fairly straightforward conversion, although you will probably want to pull up some sample queries in Postman or another API browser so you can get an idea of the data structure you receive when using the Find API. This is different, but similar to, from the structures returned by the Current Weather API.
Here is what the template should look like after you finish your edits:
<div ng-app class="jumbotron" ng-controller="MainCtrl">
<h1>Select Your City</h1>
<p class="lead">
<div ng-init="location='Seattle'">
<p>
<label for="location">Location:
<input type="text" name="location" ng-model="location">
</label>
</p>
<p>
<button class="btn btn-lg btn-primary" ng-click="findCities()">Find City</button>
</p>
</div>
<div ng-if="searchQuery">
<p class="lead">{{citiesFound.count}} cities found matching the query: {{searchQuery}}.</p>
<dl ng-repeat="city in citiesFound.list">
<dt>{{city.name}}, {{city.sys.country}}</dt>
<dd>{{city.weather[0].main}} - {{city.weather[0].description}}</dd>
<dt>Temperature</dt>
<dd>{{city.main.temp}} °F</dd>
<dd><a ng-href="/#/current/{{city.id}}" class="btn btn-lg btn-primary">View Weather</a></dd>
</dl>
</div>
</p>
</div>
We use the same text input box and button, but we will attach our findCities()
function to the button this time. You will notice that we have changed the text label, as well as the text for the title of the page.
We wrapped the results in a <div>
that is controlled by a ng-if
directive:
<div ng-if="searchQuery">
This directive only shows the element and its children if the conditional contained in the ng-if
attribute is true. In this case, the results of our search will only show if the searchQuery
variable contains a value. So when you first load the page, you will see no results, but after you submit your query and the response returns from the API the results will be shown.
Since we anticipate there will be multiple results, we use the ng-repeat
directive to specify a loop in the ng-repeat
attribute:
<dl ng-repeat="city in citiesFound.list">
In this case we loop through the city
objects in citiesFound.list
Array (which is where the OpenWeatherMap.org API puts the list of cities). Using the ng-repeat
directive causes the HTML element it's a part of to repeat for every item in an Array.
We output all the different useful information about each city so our user can understand what city has been found. The OpenWeatherMap.org API gives us some brief weather data for each city we found, so we can display some quick, useful information to our users.
Finally, we output a button to click on to view the weather for a given city:
<a ng-href="/#/current/{{city.id}}" class="btn btn-lg btn-primary">View Weather</a>
This link makes use of the ng-href
directive, which parses variables inside of the ng-href
attribute. This allows us to create a link to view current weather info about a given city. In our case, we are building the URL with the /current/
directory followed by the ID of the city: {{city.id}}
. When our users click this link, we will be able to show them the current weather data for the city.
Try it out!
Now that we have all the pieces in place, you should be able to test your creation in your browser. You should now be able to search for cities using whole names, or parts of names, and see all the cities you can find. OpenWeatherMap.org tracks weather for about 200 thousand cities, so there should be plenty to try out. Each city should come up with the name, country, and weather summary.
Once you've marveled at your amazingly awesome new city search tool, we can move on to building the current weather view in its proper location.