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>
Related
This questions comes from here
I want to make a filtering, so that I can show the values of colors.name just when they also appear as a value in cars.color
$scope.colors = [{"name":"blue","count":2},
{"name":"red","count":12},
{"name":"pink","count":5},
{"name":"yellow","count":2}];
$scope.cars=[ {"brand":"Ford","color":"blue", "seat":"pink"}
,{"brand":"Ferrari","color":"red", "seat":"pink"}
,{"brand":"Rolls","color":"blue","seat":"pink"}];
And then in the view:
<ul>
<li ng-repeat="n in colors | filter: filteredColors"> {{n}}
</li>
</ul>
The result should be
blue
red
I need the answer not to have ES6, and I need the filter to be in the controller. See plunkr here. Thanks in advance!
controller:
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.colors = [{"name":"blue","count":2},
{"name":"red","count":12},
{"name":"pink","count":5},
{"name":"yellow","count":2}];
$scope.cars=[ {"brand":"Ford","color":"blue", "seat":"pink"}
,{"brand":"Ferrari","color":"red", "seat":"pink"}
,{"brand":"Rolls","color":"blue","seat":"pink"}];
$scope.filteredColors = function(color) {
var carsvar = $scope.cars;
for(var x = 0; x < carsvar.length; x++) {
if (color.name === carsvar[x].color) {
return true;
}
}
return false;
};
});
view:
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<link rel="stylesheet" href="style.css" />
<script data-require="angular.js#1.6.x" src="https://code.angularjs.org/1.6.6/angular.js" data-semver="1.6.6"></script>
<script src="app.js"></script>
</head>
<body ng-controller="MainCtrl">
<ul>
<li ng-repeat="color in colors | filter: filteredColors"> {{color.name}}
</li>
</ul>
</body>
</html>
You can use a custom filter:
app.filter('colorFilter', function(){
return function(val){
var colorsvar = [{"name":"blue","count":2},
{"name":"red","count":12},
{"name":"pink","count":5},
{"name":"yellow","count":2}];
var filtered = []
angular.forEach(val, function(key, value){
angular.forEach(colorsvar, function(key2, value2){
if(key.color === key2.name)
filtered.push(key)
})
})
return filtered;
}
})
And then on your html:
<li ng-repeat="n in cars | colorFilter"> {{n.color}}
Hope this helps.
As per your first question, there have some answers without using ES6. AngularJS - How to check that a specific key has a specific value in an array
So I thought you don't need to use any inbuilt function to do your logic.
Try to use with manual loop instead of using map or include bla bla bla.. Do Just like a normal JavaScript way in angularjs. Get this answer as a key. Take this answer as a key and do it with angular.filter().
var app = angular.module("myApp",[]);
app.controller("myCtrl",function($scope){
$scope.colors = [{"name":"blue","count":2},
{"name":"red","count":12},
{"name":"pink","count":5},
{"name":"yellow","count":2}];
$scope.cars=[ {"brand":"Ford","color":"blue"}
,{"brand":"Ferrari","color":"red"}
,{"brand":"Rolls","color":"blue"}];
$scope.filteredColors = function () {
var colorsvar = $scope.colors;
var carsvar = $scope.cars;
$scope.newValue = [];
for (var i = 0; i < colorsvar.length; i++) {
for (var j = 0; j < carsvar.length; j++) {
if (colorsvar[i].name == carsvar[j].color) {
if ($scope.newValue.indexOf(colorsvar[i].name) ==-1) {
$scope.newValue.push(colorsvar[i].name);
}
}
}
}
return $scope.newValue;
};
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myCtrl">
<ul>
<li ng-repeat="n in filteredColors()"> {{n}}
</li>
</ul>
</div>
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);
};
});
I am creating a Phonegap app (Android and iOS) using AngularJS and Websql.
My problem is that i am finding it difficult getting from the Websql query into controller/view.
This is my code.
<!doctype html>
<html ng-app="inmoment">
<head>
<meta charset="utf-8">
<title>My App</title>
<script src="lib/jquery-2.1.1.min.js"></script>
<script src="lib/angular.min.js"></script>
<script src="lib/angular-resource.min.js"></script>
<script src="js/catMenu.js"></script>
<script src="js/models.js"></script>
<script src="js/controllers.js"></script>
</head>
<body>
<ul ng-controller="sampleController">
<li ng-repeat="cat in cats">
{{cat.catID}}<br />
{{cat.Title}}<br />
{{cat.cCount}}<br />
{{cat.mCount}}
</li>
</ul>
<script src="js/my-app.js"></script>
</body>
</html>
Controller Script
var inmomentNameSpace = angular.module('inmoment', []);
inmomentNameSpace.controller('sampleController', function sampleController(
$scope) {
db.transaction(function(tx) {
$("#catList").empty();
tx.executeSql(
'SELECT CATEGORY.catID, CATEGORY.Title, CATEGORY.image, COUNT(SUBCATEGORY.subID) as cCount, COUNT(MESSAGETB.mesID) as mCount, SUBCATEGORY.title, SUBCATEGORY.catID FROM CATEGORY LEFT OUTER JOIN SUBCATEGORY ON CATEGORY.catID = SUBCATEGORY.catID LEFT OUTER JOIN MESSAGETB ON SUBCATEGORY.subID = MESSAGETB.subID GROUP BY CATEGORY.catID ORDER BY CATEGORY.Title ASC', [],
function(tx, results) {
var len = results.rows.length;
var catObj = [];
for (var i = 0; i < len; i++) {
catObj[i] = results.rows.item(i);
}
console.log(catObj);
$scope.cats = catObj;
})
})
})
When I console.log(catObj), I get the results alright, but they seem not work with my controller.
I will be glad if anyone can help me. Thank you
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
i am trying to output array values via a click using backbone view model, please advise how to output each array values on a separate line or maybe displaying each array value in a list item via jquery. Thanks :)
<!DOCTYPE html>
<head>
<meta charset=utf-8" />
<title>Test</title>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript" src="underscore.js"></script>
<script type="text/javascript" src="backbone.js"></script>
</head>
<body>
<button>click</button>
<div class="ctype"></div>
<div class="cexperience"></div>
<script type="text/javascript">
var Job1 = Backbone.Model.extend({
defaults:{
type:'permanent',
experience:['html','css','php']
}
});
var myJob1 = new Job1();
var Jobview1 = Backbone.View.extend({
el:'button',
events:{
'click':'render'
},
render: function(){
var _type = myJob1.get('type');
var _experience = myJob1.get('experience');
$('div.ctype').html(_type);
$('div.cexperience').html(_experience);
return this
}
})
$(document).ready(function(e) {
var myJobview1 = new Jobview1();
});
</script>
</body>
</html>
_.each(_experience, function (key, value) {
var tmp = $('<p />');
tmp.html(value);
$('.experience').append(tmp);
)};
this should work.
maybe you need to switch key, value to value, key.
i tend to forget the order of the parameters.