Reputation: 195
I've built a basic Angular app that successfully displays the results of an HTTP GET request.
I'd like to include fallback code that displays two static HTML elements in place of the remote content if the GET request fails.
I can just call a vanilla JS function to do DOM manipulation, but I'd like to do this the Angular way. I've read a lot of documentation and articles, but I'm not seeing a straightforward way to do this. Code below.
I'd like to replace the call to updateUIError() with Angular code that performs the same task.
Here's a Plunk: https://plnkr.co/edit/PDwSUCXGNW2cwAIwl9Z9?p=streamer
HTML:
<div class="scene fullheight" id="attractions" ng-app="listApp">
<article class="content">
<h1>Upcoming Events</h1>
<div class="main" ng-controller="ListController as eventsList">
<div class="search">
<label>search: </label>
<input ng-model="query" placeholder="Search for events" autofocus>
<label class="formgroup">by:
<select ng-model="eventOrder" ng-init="eventOrder='start.local'">
<option value="start.local">Date</option>
<option value="name.text">Name</option>
</select>
</label>
<label class="formgroup">
<input type="radio" ng-model="direction" name="direction" checked>
ascending
</label>
<label class="formgroup">
<input type="radio" ng-model="direction" name="direction" value="reverse">
descending
</label>
</div>
<ul class="eventlist">
<li class="event cf" ng-repeat="item in eventsList.events | filter: query | orderBy: eventOrder:direction">
<div class="info">
<h2><a href="{{item.url}}" target="_blank">{{item.name.text}}</a></h2>
<p>{{item.start.local | date:"dd MMMM ', ' h:mma"}}</p>
</div>
</li>
</ul>
</div>
</article>
</div>
Angular:
angular.module('listApp', [])
.controller('ListController', ['$scope', '$http', function($scope,$http) {
var eventsList = $scope.eventsList;
$http.get(URI)
.success(function(data) {
console.log(data);
eventsList.events = data.events;
}).error(function() {
updateUIError();
});
}]);
function updateUIError() {
var events = document.querySelector('#attractions article');
events.innerHTML = '<h1>Local Attractions</h1><p>There's lots to do nearby.</p>';
}
Upvotes: 1
Views: 319
Reputation: 12025
You need to create a static error and show it when the error occurs using ngIf
<div class="scene fullheight" id="attractions" ng-app="listApp">
<div ng-controller="ListController">
<article class="content" ng-if="hasUIError">
<h1>Local Attractions</h1>
<p>There's lots to do nearby.</p>
</article>
<article class="content" ng-if="!hasUIError">
<h1>Upcoming Events</h1>
<!-- REST OF THE HTML -->
</article>
</div>
</div>
Then, in your controller, you need to set the flag to false
by default:
$scope.hasUIError = false;
And when there's an error in the ajax, set it to true
$http.get(URI).then(
function(response) {
console.log(response);
$scope.events = response.data.events;
},
function() {
$scope.hasUIError = true;
}
);
Upvotes: 2
Reputation: 994
Do something like this:
angular.module('listApp', [])
.controller('ListController', ['$scope', '$http', function($scope,$http) {
var eventsList = $scope.eventsList;
$http.get(URI)
.success(function(data) {
console.log(data);
eventsList.events = data.events;
}).error(function() {
eventsList.errorMessage = '<h1>Local Attractions</h1><p>There's lots to do nearby.</p>';
});
}]);
In the HTML, add a span inside the scope of ListController that will have ngModel="errorMessage". You can add additional property to show / hide the error span and main content div.
Upvotes: 0
Reputation: 3025
Before solving your issue, there is another issue to address. Specifically, since you are using the ControllerAs approach, you'll want to attach your variables to 'this' rather than $scope.
Then you create a variable called showError that will get evaluated in showing the message. Then you can use the ng-show directive to hide/show the message.
angular.module('listApp', [])
.controller('ListController', ['$http',
function($http) {
var vm = this;
vm.events = [];
vm.showError = false;
$http.get(URI)
.success(function(data) {
vm.events = data.events;
}).error(function() {
vm.showError = true;
});
}
]);
<!DOCTYPE html>
<html ng-app="listApp">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>
document.write('<base href="' + document.location + '" />');
</script>
<link rel="stylesheet" href="style.css" />
<script data-require="[email protected]" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.10/angular.min.js" data-semver="1.5.10"></script>
<script src="app.js"></script>
</head>
<body ng-controller="ListController as eventsList">
<div class="scene fullheight" id="attractions">
<div ng-show="eventsList.showError">
<h1>Local Attractions</h1>
<p>There's lots to do nearby.</p>
</div>
<article class="content">
<h1>Upcoming Events</h1>
<div class="main">
<div class="search">
<label>search:</label>
<input ng-model="query" placeholder="Search for events" autofocus>
<label class="formgroup">by:
<select ng-model="eventOrder" ng-init="eventOrder='start.local'">
<option value="start.local">Date</option>
<option value="name.text">Name</option>
</select>
</label>
<label class="formgroup">
<input type="radio" ng-model="direction" name="direction" checked>ascending
</label>
<label class="formgroup">
<input type="radio" ng-model="direction" name="direction" value="reverse">descending
</label>
</div>
<ul class="eventlist">
<li class="event cf" ng-repeat="item in eventsList.events | filter: query | orderBy: eventOrder:direction">
<div class="info">
<h2><a href="{{item.url}}" target="_blank">{{item.name.text}}</a></h2>
<p>{{item.start.local | date:"dd MMMM ', ' h:mma"}}</p>
</div>
</li>
</ul>
</div>
</article>
</div>
</body>
</html>
Upvotes: 2