Searching NYT API using Angular JS - javascript

I am writing code in Angular JS implement a standard application which would show a search field and a search button the screen and when a search is run, it should pull in the remote result and display them on the screen
Console is not showing any errors to me but i cant get to display the results on the screen.I am wondering how do i display the results on the screen
here is the code in my js file
angular.module('plunker', [])
.controller('MainCtrl', ['$scope', '$http',
function($scope, $http) {
var clearError = function(result) {
$scope.error = "";
return result;
};
var applyData = function(result) {
$scope.articles = result.data;
console.log(result.data);
};
var rejected = function(error) {
$scope.error = error.message;
};
var getArticles = function() {
var url = "http://api.nytimes.com/svc/search/v2/articlesearch.json?q=North+Korea&api-key=052861d142cf4eb7fa12bb79781fdbe1:11:69591426";
var promise = $http({
method: 'GET',
// https://jsonp.nodejitsu.com
url: "https://jsonp.nodejitsu.com/?url=" + encodeURIComponent(url)
});
promise.success(clearError).then(applyData);
promise.error(function(error) {
$scope.error = error.message;
});
};
getArticles();
$scope.getRepos = _.debounce(getArticles, 300);
}]);
And here is the html code
<!DOCTYPE html>
<html ng-app="plunker">
<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="lodash.js#*" data-semver="2.4.1" src="http://cdnjs.cloudflare.com/ajax/libs/lodash.js/2.4.1/lodash.js"></script>
<script data-require="angular.js#1.2.x" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.17/angular.min.js" data-semver="1.2.17"></script>
<script src="script.js"></script>
</head>
<body ng-controller="MainCtrl">
<input ng-keyup="getArticles()" />
<table>
<thead>
<tr>
<td>Headline</td>
<td>Body</td>
</tr>
</thead>
<tbody>
<tr ng-bind="error" style="color:red;"></tr>
<tr ng-repeat="a in Articles">
<td>{{a.headline}}</td>
<td>{{a.body}}</td>
</tr>
</tbody>
</table>
</body>
</html>

You have several issues.
In scope you have articles but in html it is Articles.
To access the actual data you want in response you need to look deeper inside the data object returned:
Try changing:
var applyData = function(result) {
$scope.articles = result.data;
console.log(result.data);
};
To:
var applyData = function(result) {
var articles=result.data.response.docs
$scope.articles = articles;
console.log(articles);
};
Then in the html you need slightly different properties since headline has sub properties like main and print_headline
As example
<tr ng-repeat="a in articles">
<td>{{a.headline.main}}</td>
<td>{{a.lead_paragraph}}</td>
</tr>
DEMO

Related

Pluralsight - AngularJS: Get Started

I follow the "AngularJS: Get Started" course from Plualsight, and I reach the Routing module, so I have some files in Plunker, on the course they can see on Preview page the title which is "Github Viewer" and a search bar. But I still get errors in console, and I do not know why, my code should be identical as their code.
So I have the following files :
app.js
(function() {
var app = angular.module('githubViewer', ["ngRoute"]);
app.config(function($routeProvider) {
$routeProvider
.when("/main", {
templateUrl: "main.html",
controller: "MainController"
})
.otherwise({redirectTo: "/main"});
});
}());
github.js
(function() {
var github = function($http) {
var getUser = function(username) {
return $http.get("https://api.github.com/users/" + username)
.then(function(response) {
return response.data;
});
};
var getRepo = function(user) {
return $http.get(user.repos_url)
.then(function(response) {
return response.data;
});
};
return {
getUser : getUser,
getRepo : getRepo
};
};
var module = angular.module("githubViewer");
module.factory("github", github);
}());
index.html
<!DOCTYPE html>
<html ng-app="githubViewer">
<head>
<script data-require="angular.js#*" data-semver="1.3.14" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.14/angular.min.js"></script>
<script data-require="angular-route#*" data-semver="1.6.2" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.2/angular-route.js"></script>
<link rel="stylesheet" href="style.css" />
<script scr="app.js"></script>
<script src="MainController.js"></script>
<script src="github.js"></script>
</head>
<body>
<h1>Github Viewer</h1>
<div ng-view></div>
</body>
</html>
main.html
<div>
{{ countdown }}
<form name="searchUser" ng-submit="search(username)">
<input type="search" required="" ng-model="username" />
<input type="submit" value="Search" />
</form>
</div>
MainController.js
// Code goes here
(function() {
var app = angular.module("githubViewer");
var MainController = function($scope, $interval, $location) {
console.log("Atentie!")
var decrementCountdown = function() {
$scope.countdown -= 1;
if ($scope.countdown < 1) {
$scope.search($scope.username);
}
};
var countdownInterval = null;
var startCountdown = function() {
countdownInterval = $interval(decrementCountdown, 1000, $scope.countdown);
};
$scope.search = function(username) {
if (countdownInterval) {
$interval.cancel(countdownInterval);
$scope.countdown = null;
}
//
};
$scope.username = "Angular";
$scope.countdown = 5;
startCountdown();
};
app.controller("MainController", MainController);
}());
userdetails.html
<div id="userDetails">
<h2>{{user.name}}</h2>
<img ng-src="{{user.avatar_url}}" title="{{user.name}}">
<div>
Order:
</div>
<select ng-model="repoSortOrder">
<option value="+name">Name</option>
<option value="-stargazers_count">Stars</option>
<option value="+language">Language</option>
</select>
</div>
<table>
<thead>
<tr>
<th>Name</th>
<th>Stars</th>
<th>Language</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="repo in repos | limitTo:10 | orderBy:repoSortOrder">
<td>{{repo.name}}</td>
<td>{{repo.stargazers_count | number }}</td>
<td>{{repo.language}}</td>
</tr>
</tbody>
</table>
And the style.css which is empty.
So at this point I should see in a separete window something like in the following picture and no errors in console.
But I se only the title, like in the following picture
and errors
Could someone help me to understand why isnt' work ?
Was some changes in AngularJS and the course isn't up to date ?
You made a typo
<script scr="app.js"></script>
should be
<script src="app.js"></script>
Also make sure that when using angularjs core api's, all the API should be off same version. Here you're using angularjs (ver. 1.3.12) & angular-route (ver. 1.6.2)
Change both to 1.6.2 or latest
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.2/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.2/angular-route.js"></script>
Demo Here

How to send an angular param to an onclick event?

here we go...
I have a controller
$scope.selectedScript = {};
$scope.selectedScript.scriptId = null;
$scope.selectScript = function(script, index) {
$scope.selectedScript = script;
$scope.selectedRow = index;
myAppFactory.updateTextArea(script).success(
function(data) {
$scope.selectedScript = data;
});
};
$scope.getSelectedClass = function(script) {
if ($scope.selectedScript.scriptId != undefined) {
if ($scope.selectedScript.scriptId == script.scriptId) {
return "selected";
}
}
return "";
};
i have a html page
<label>Script ID:</label>
<input name="scriptId"
type="text"
id="scriptId"
ng-model="selectedScript.scriptId"
ng-disabled="true"
value="{{selectedScript.scriptId}}" />
and now thx to IARKI i have this
<script type="text/javascript">
function goTo (){
var param1 = angular.element(document.querySelector('.scriptId')).scope.selectedScript.scriptId;
location.href=this.href + '?scriptId='+param1;
return false;
}
</script>
Debug
I have also a list of scripts in a table
<table class="scripts" name="tableScript" arrow-selector>
<tr bgcolor="lightgrey">
<th>Script ID</th>
<th>File Name</th>
</tr>
<tr
ng-repeat="s in scripts | filter:searchField | orderBy:'scriptId'"
ng-click="selectScript(s, $index)" ng-class="getSelectedClass(s)">
<td>{{s.scriptId }}</td>
<td>{{s.fileName }}</td>
</tr>
</table>
Then i press the link above, and a new tab appears, but the link is still the
http://localhost:8080/DSS-war/debug.html
but i need it to open in a new tab as well as to be like this:
http://localhost:8080/DSS-war/debug.html?scriptId=1
http://localhost:8080/DSS-war/debug.html?scriptId=2
http://localhost:8080/DSS-war/debug.html?scriptId=12
and so on...with numbers
any idea?
And it has to be the onclick function, not the ng-click
I know how it works on ng-click, but i need to make it work on onclick...
and now i get this from the chrome debugger:
Uncaught TypeError: Cannot read property 'scriptId' of undefined
in the line
var param1 = angular.element(document.querySelector('.scriptId')).scope.selectedScript.scriptId;
You can try to access angular scope using pure javascript
<script type="text/javascript">
function goTo (){
var param1 = angular.element("#scriptId").scope().selectedScript.scriptId;
location.href=this.href + '?scriptId='+param1;
return false;
}
</script>
Debug
Update
Useless code but I hope it will help you
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>My application</title>
</head>
<body ng-app="myApp" ng-controller="myCtrl">
<label>Script ID:</label>
<input name="scriptId" type="text" id="scriptId" ng-model="selectedScript.scriptId" ng-disabled="true">
<button onclick="generateID()">Set code</button>
Debug
</body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.min.js"></script>
<script type="text/javascript">
function generateID() {
var code = Math.floor(Math.random() * 20) + 1;
document.getElementById('scriptId').setAttribute('value', code.toString());
}
function goTo() {
var scope = angular.element(document.querySelector('#scriptId')).scope();
scope.$apply(function () {
scope.selectedScript.scriptId = document.querySelector('#scriptId').getAttribute('value');
});
scope.changeURl();
}
angular.module('myApp', [])
.controller('myCtrl', function ($scope, $window) {
$scope.selectedScript = {};
console.log('We are in controller');
$scope.changeURl = function () {
$window.open('http://localhost:8080/DSS-war/debug.html?scriptId=' + $scope.selectedScript.scriptId, '_blank');
}
});
</script>
</html>

AngularJS - Filter requires string despite being a string

I am getting the following error: Error: [$sce:itype] Attempted to trust a non-string value in a content requiring a string: Context: html on this simple code despite its typeof() saying it is a string...
var app = angular.module('app', ['angular.filter', 'ngSanitize']);
app.controller('MainCtrl', ['$scope', '$filter', function($scope, $filter) {
$scope.filters = {};
this.people = [{
name: 'Yasuhito Endo'
}, {
name: 'Dejan Damjanović'
}, {
name: 'Gao Lin'
}, {
name: 'Mohammed Noor'
}];
this.applyFilter = function() {
console.log('Making first names bold...');
this.people = $filter('nameBold')(this.people);
}
}]);
app.filter('nameBold', function($sce) {
return function(items) {
var filtered = [];
angular.forEach(items, function(item) {
var splitIt = item.name.split(" ");
item.name = '<strong>' + splitIt[0] + '</strong> ' + splitIt[1];
console.log('Trusting... ' + typeof(item.name));
// Trusting... string (4x) |
// OUTPUT ------------------
// It outputs as a string yet it gives me the error:
// Error: [$sce:itype] Attempted to trust a non-string value
// in a content requiring a string: Context: html
// --------------------------------
// https://docs.angularjs.org/error/$sce/itype?p0=html
filtered.push(item.name);
});
return $sce.trustAsHtml(filtered);
};
});
<!DOCTYPE html>
<html ng-app="app">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<script data-require="angular.js#1.4.x" src="https://code.angularjs.org/1.4.8/angular.js" data-semver="1.4.8"></script>
<script data-require="angular-filter#*" data-semver="0.5.2" src="https://cdnjs.cloudflare.com/ajax/libs/angular-filter/0.5.2/angular-filter.js"></script>
<script data-require="lodash.js#*" data-semver="3.10.0" src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.0/lodash.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular-sanitize.min.js"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl as viewmodel">
<button ng-click="viewmodel.applyFilter()">Apply the Filter</button>
<div ng-repeat="person in viewmodel.people">
Person: <span ng-bind-html="person.name"></span>
</div>
</body>
</html>
Plunker snippet: http://plnkr.co/edit/rIlETpJ3GeW0YYqrc8NB?p=preview
As you can see from the code, it looks very simple yet the returned item is a string and yet it gives me that big, nasty error.
How do I fix this?
Thanks.
I figured it out. Just take what you put as variable (From object) and put it as as new variable to a string.
app.filter('nameBold', function($sce) {
return function(items) {
var filtered = [];
var itemName = "";
angular.forEach(items, function(item) {
var splitIt = item.name.split(" ");
item.name = '<strong>'+splitIt[0]+'</strong>';
itemName = item.name;
filtered.push(item.name);
});
return $sce.trustAsHtml(itemName);
};
});

Get id of the HTML element with AngularJS

I need to get the specific id of each line and forward to a JS function that will make an http request. But I'm having trouble calling this function, excluir(id), the parameters are correct but the alert doesn't run. Why is that?
HTML
<!DOCTYPE html>
<html ng-app="oknok">
<head lang="pt-br">
<meta charset="UTF-8"/>
<title>OKNOK Admin</title>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.1/angular.min.js"></script>
<script src="js/controller.js"></script>
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
</head>
<body ng-controller="indexController" data-ng-init="init()">
<div class="container">
<h2>Listagem de veículos</h2>
<table class="table table-condensed">
<thead>
<tr>
<th>Nome</th>
<th>Tipo</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="x in resultado">
<td ng-model="nome">{{x.nome}}</td>
<td ng-model="tipo">{{x.tipo}}</td>
<td ng-model="lixeira"><span class="glyphicon glyphicon-trash" ng-click="excluir({{x._links.self.href}})"></span></td>
</tr>
</tbody>
</table>
<div align="right">
<button type="button" class="btn btn-primary" ng-click="adicionarNovo()">Adicionar novo</button>
</div>
</div>
</body>
</html>
Controller.js
var oknok = angular.module('oknok', []);
oknok.controller('indexController', function ($scope, $http) {
$scope.init = function () {
$http.get("/api/veiculos")
.then(function (data) {
var embedded = data.data._embedded;
$scope.resultado = embedded.veiculos;
}).catch(function (error) {
alert("Erro ao obter dados!\n" + error);
});
};
$scope.adicionarNovo = function () {
window.location.href = "/cadastro";
};
$scope.excluir = function (id) {
alert("clicou" + "\t" + id);
}
});
The functions don't need {{}} as everybody said before on ng-click remove them.
Like that :
ng-click="excluir(x._links.self.href)"
Try injecting "$window" instead. That way, you'll be sure the window object has the proper angular lifecycle:
var oknok = angular.module('oknok', []);
oknok.controller('indexController', function ($scope, $http, $window) {
$scope.init = function () {
$http.get("/api/veiculos")
.then(function (data) {
var embedded = data.data._embedded;
$scope.resultado = embedded.veiculos;
}).catch(function (error) {
$window.alert("Erro ao obter dados!\n" + error);
});
};
$scope.adicionarNovo = function () {
$window.location.href = "/cadastro";
};
$scope.excluir = function (id) {
$window.alert("clicou" + "\t" + id);
}
});

Limit typeahead results

I'm using the angular-ui typeahead directive to connect to the Google Maps API and retrieve an array of addresses. Normally when I need to limit the amount of results visible I do something like:
<input typeahead="eye for eye in array | filter:$viewValue | limitTo:10">
That works perfectly and the results are limited to 10. However, when I try to do the same thing with asynchronous results, it doesn't work. It will give more results than I specified in the limitTo.
Am I doing something incorrectly below?
Here is a plunker:
HTML:
<input ng-model="asyncSelected" typeahead="address for address in getLocation($viewValue) | limitTo:1" typeahead-loading="loadingLocations">
JavaScript:
$scope.getLocation = function(val) {
return $http.get('http://maps.googleapis.com/maps/api/geocode/json', {
params: {
address: val
}
}).then(function(res){
var addresses = [];
angular.forEach(res.data.results, function(item){
addresses.push(item.formatted_address);
});
return addresses;
});
};
Currently i'm doing the following to workaround, i'm just curious why a simple limitTo doesn't work.
$scope.getLocation = function(val) {
return $http.get('http://maps.googleapis.com/maps/api/geocode/json', {
params: {
address: val
}
}).then(function(res){
var addresses = [];
var resultNumber = res.data.results.length > 5 ? 5 : res.data.results.length;
for(var i = 0; i < resultNumber; i++){
var obj = res.data.results[i];
var addr = obj.formatted_address;
addresses.push(addr);
}
return addresses;
});
};
typeahead doesn't seem to support promises. So it's better to just bind it to a collection, and then update that collection when you get a response from google. You might want to think about debouncing tough, now a request is done for every letter typed.
Note that you also don't need the filter anymore, because the filter is already being done by google sever side.
http://plnkr.co/edit/agwEDjZvbq7ixS8El3mu?p=preview
var app = angular.module('app',['ui.bootstrap']);
app.controller('Ctrl', ['$scope','$http', function($scope,$http){
$scope.locations = [];
$scope.$watch('asyncSelected', function(val) {
$http.get('http://maps.googleapis.com/maps/api/geocode/json', {
params: {
address: val
}
}).then(function(res){
$scope.locations.length = 0;
angular.forEach(res.data.results, function(item){
$scope.locations.push(item.formatted_address);
});
});
});
}]);
<head>
<link data-require="bootstrap-css#~3.1.1" data-semver="3.2.0" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css" />
<script data-require="angular.js#*" data-semver="1.3.0-beta.5" src="https://code.angularjs.org/1.3.0-beta.5/angular.js"></script>
<script data-require="ui-bootstrap#*" data-semver="0.11.0" src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.11.0.min.js"></script>
<script data-require="jquery#*" data-semver="2.1.1" src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script data-require="bootstrap#*" data-semver="3.1.1" src="//netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-app="app" ng-controller="Ctrl">
<input type="text" ng-model="asyncSelected" placeholder="Address" typeahead="address for address in locations | limitTo:1" typeahead-loading="loadingLocations" class="form-control">
</body>
</html>

Categories

Resources