I'm using REST Countries web service and I want to have an autocomplete feature when user is starting to type in input field, and when some country was selected to display an info about it. Want to do it with factories or maybe a directive, don't know what solution is the best
Here is what I have for now:
REST service link: https://restcountries.eu/
HTML:
<div class="container" ng-controller="CountriesController">
<h3 id="title">Countries Database</h3>
<input type="text" id="countrySearch" ng-model="selected" typeahead="country for country in countries | limitTo:8" />
<ng-view></ng-view>
</div>
Template:
<div ng-controller="CountriesController">
<ul>
<li ng-repeat="country in countries" id="countryInfo">
<p><b>Country:</b> {{country.name}}</p>
<p><b>Native Name:</b> {{country.nativeName}}</p>
<p><b>Capital:</b> {{country.capital}}</p>
<p><b>Region:</b> {{country.region}}</p>
<p><b>Subregion:</b> {{country.subregion}}</p>
<p><b>Borders:</b> {{borders}}</p>
<p><b>Languages:</b> {{languages}}</p>
<p><b>Population:</b> {{country.population}} people</p>
<p><b>Area:</b> {{country.area}} sq.km</p>
<p><b>Currencies:</b> {{currencies}}</p>
<p><b>Timezones:</b> {{timezones}}</p>
<p><b>Calling Code:</b> +{{callingCodes}}</p>
</li>
</ul>
Controller:
app.controller('CountriesController', function ($scope, CountriesFactory) {
CountriesFactory.getCountry().then(function (data) {
$scope.selected = undefined;
$scope.countries = data;
console.log($scope.countries);
$scope.timezones = data[0].timezones.toString();
$scope.languages = data[0].languages.toString();
$scope.currencies = data[0].currencies.toString();
$scope.borders = data[0].borders.toString();
$scope.callingCodes = data[0].callingCodes.toString();
});
});
Factory:
app.factory('CountriesFactory', function ($http, $q) {
return {
getCountry: function () {
var input = $('#countrySearch').val();
var request = 'https://restcountries.eu/rest/v1/name/';
var url = request + input;
return $http.get(url);
}
}
});
Checkout bootstrap UI's autocomplete widget
Look at the source code to see how it is implemented
If you go to rest countries here you can see the example how to get the rest countries like: example
The restcountries.eu/rest/v1/name is not working because they don't expose that page.
Try to make sure you have something into input. Try to check if
$('#countrySearch').val();
is not null or empty first.
Related
I have a basic controller that displays my Software Group name:
var SoftwareGroupApp = angular.module('SoftwareGroupApp', []);
SoftwareGroupApp.controller('SoftwareGroupController', function($scope, $http) {
$http.get("select_SoftwareGroup.php")
.then(function (response) {$scope.result = response.data.records;});
});
In my view I'm displaying this Software Group in a list
<ul class="sub-menu">
<div ng-app="SoftwareGroupApp" ng-controller="SoftwareGroupController">
<li ng-repeat="x in result"><a class="haschild" title="" href="">{{ x.GroupName }}</a>
<ul>
<div ng-controller="SoftwareController">
<li ng-repeat="x in names"><a title="" href="">{{ x.name }}</a></li>
</div>
</ul>
</li>
</div>
</ul>
and i have another controller that display my Software name :
var SoftwareApp = angular.module('SoftwareApp', []);
SoftwareApp.controller('SoftwareController', function($scope, $http) {
$http.get("selectSoftware.php")
.then(function (response) {$scope.names = response.data.records;});
});
when someone click on the Software Group name, i have another sub menu that list my software name .
<ul>
<div ng-controller="SoftwareController">
<li ng-repeat="x in names"><a title="" href="">{{ x.name }}</a></li>
</div>
</ul>
What I'm trying to do is when someone click on the Software Group name, my Software group id save in a variable and send to my SoftwareController . and i display names of software that == id
I would suggest you to use $rootScope.broadcast for this kind of operation. To be very short you can use broadcast like this.
I one controller where you want to send data write like this:
$rootScope.$broadcast("yourFuction", data);
In the receiver controller get this data like this:
$rootScope.$on("yourFuction", function(data){
//do something
});
check this for more information: https://docs.angularjs.org/api/ng/type/$rootScope.Scope
Thanks.
Your best solution would be to use uirouter, rather than ng-controller, and pass the ID as a state parameter.
Another option would be to use components rather than ng-controller, which you can pass parameters to.
There are so many ways. I will mention you one way:
You can create a service to store Id which you want to send into another controller like below:
angular.module('app').factory('commonService', function () {
var myValue;
return {
set: function (o) {
this.myValue = o;
},
get: function () {
return this.myValue;
}
};
});
Now, inject this service into both controller like below:
angular.module('app').controller('firstController', function ($scope, commonService) {
$scope.setValue = function (value) {
commonService.set(value);
};
});
And,
angular.module('app').controller('SecondController', function ($scope, commonService) {
$scope.getValue = function () {
$scope.value = commonService.get();
};
});
I have defined a controller like this :
app.controller("home", function ($scope, $http, $common) {
$http({
method: "GET",
url: '/posts/loadData'
}).then(function (response) {
//console.clear()
if (typeof response.data.posts != 'undefined') {
console.log(response.data.posts);
$scope.posts = $common.arrangePosts(response.data.posts);
}
});
})
and a service to arrange data :
app.service('$common', function ($timeout, $sce, $httpParamSerializerJQLike) {
var that = this;
this.arrangePosts = function (rawPosts) {
var posts = [];
$.each(rawPosts, function (key, value) {
posts.push({
postId: value.postId,
postLink: '/post/' + that.cleanString(value.title) + '/' + value.postId,
title: value.title,
summary: $sce.trustAsHtml(value.summary)
});
});
return posts;
}
});
using values in html like this :
<div class="widget fullwidth post-single">
<h4 class="widget-title">Latest</h4>
<div class="widget-content">
<ul>
<li ng-repeat="post in posts">
<h4 class="list-title">{{post.title}}</h4>
{{post.summary}}
</li>
</ul>
</div>
</div>
Data coming from server in JSON form :
Object { postId="4", title="asdf", summary="<p>asdf</p>"}
but all the html tags are printing on my page as it is (like a text) in summary.
In many SO posts people suggested to use $sce.trustAsHtml but its not working for me. Please suggest anyway to solve my problem.
Any help will be appreciated..!!
have you tried this?
<div ng-bind-html='post.summary'></div>
You could solve this over a directive. Did you know, that you can use JQuery Lite inside AngularJS to manipulate the DOM?
Here a quick example:
angular.module("PostsDirective",[])
.directive("posts", function($sce){
return {
link: function($scope, $element, $attrs){
//the HTML you want to show
var post = "<div>hello world</div>";
var posts = [post,post,post,post];
//iterating through the list (_.each is a function from underscore.js)
_.each(posts, function(element){
//if you want to save the trusted html string in a var you can do this with getTrustedHtml
//see the docs
var safeHtml = $sce.getTrustedHtml($sce.trustAsHtml(element));
//and here you can use JQuery Lite. It appends the html string to the DOM
//$element refers to the directive element in the DOM
$element.append(safeHtml);
});
}
};
});
And the html
<posts></posts>
This also pretty nice for the readability for your HTML code. And you can use it everywhere on your page.
BTW:
As i can see, you get the HTML elements directly from a REST-Service. Why don't you get just the data and insert it into the ng-repeat? If you transfer all the HTML you get a pretty high overhead if you have loads of data.
Using Angular and Angular UI Bootstrap I need to combine results from 2 feeds into a single typeahead dropdown. I will combine results from the Google places JSON feed with results from my application, into a single set of Typeahead dropdown results.
Is this possible to combine both feeds in a promise? I have tried using the $q method, but I can't seem to get this working. This is what I've tried so far. Non-working JS Fiddle is here:
http://jsfiddle.net/rfnegz60/1/
HTML
<div ng-app="dr" ng-controller="testCtrl">
<input type="text" ng-model="asyncSelected" placeholder="Locations loaded via $http" typeahead="address for address in getCombinedLocations($viewValue)" typeahead-loading="loadingLocations" class="form-control">
<i ng-show="loadingLocations" class="glyphicon glyphicon-refresh"></i>
</div>
JavaScript
var app = angular.module('dr', ['ui.bootstrap']);
app.controller("testCtrl", function ($scope, $http, $q) {
$scope.selected = undefined;
$scope.getCombinedLocations = function(val) { $q.all(['http://maps.googleapis.com/maps/api/geocode/json','http://maps.googleapis.com/maps/api/geocode/json']).then(function(results){
// return results;
$scope.combined = [];
angular.forEach(results, function(result){
$scope.combined.push(result.data);
return $scope.combined;
});
})}
});
You should be passing not just a URL but a whole $http.get request to the Promise. See the updated fiddle here: http://jsfiddle.net/rfnegz60/3/
$q.all([$http.get('http://maps.googleapis.com/maps/api/geocode/json', {
params: {
address: val,
sensor: false
}
}),$http.get('http://maps.googleapis.com/maps/api/geocode/json', {
params: {
address: val,
sensor: false
}
})])
I tried to get the HTML page value to angularJS function , The below steps are which i tried.
HTML page :
<label class="item-input item-stacked-label">
<span class="input-label cont_det_label">First Name</span>
<p class="contact_display" id="txtFirstName" ng-model="testName">Satya</p>
</label>
angularJS Page :
.controller('SocialNetworkCtrl', ['$scope','$http','$state','ContactsService','$ionicNavBarDelegate','$ionicLoading','$ionicPopup',function($scope, $http, $state, ContactsService, $ionicNavBarDelegate, $ionicLoading,$ionicPopup) {
$scope.showUserProfile = function() {
$state.go("linkedin");
var firstname = (document.getElementById("txtFirstName").value);
}
}])
So I need var firstname = Satya ?? Is it correct way please guide me to access this value .
var firstName = $scope.testName
<input ng-model="testName" />
testName is the ng-model name that you have give. It will be automatically binded to your controller. No need the get the value using document.getElementById
Wrong usage , why ng-model in <p> tag??
Update
Change your fiddle with the following code, it will work. Also make sure framework is selected properly (as in the image)
<div ng-app ng-controller="testController">
<input ng-model="testDataName" ng-change="check()" /> {{testDataName}}
After ng-change : {{checkName}}
</div>
function testController($scope) {
$scope.testDataName="Dummy Name";
$scope.check = function () {
$scope.checkName=$scope.testDataName;
console.log($scope.checkName);
};
}
its a text node, you will require .innerHTML or '.innerText', .value is for form inputs
var firstname = (document.getElementById("txtFirstName").innerHTML);
and don't use ng-model on a p element, change it to like this
<p class="contact_display" id="txtFirstName">{{testName}}</p>
just use $scope.testName to get the value, no need for firstname = (document.getElementById("txtFirstName").innerHTML); querying DOM for value is jQuery style, use angular the $scope for 2 way bindings
Read more at official doc
Update here is updated function on loginCtrl
.controller('loginCtrl', ['$scope', function ($scope) {
$scope.testNameData = 'Satya';
$scope.doLogin = function() {
alert($scope.testNameData);
};
}])
If you really want to go jQuery way here is what you can do, its not recommended, you should use angular directive to do DOM manipulation
$scope.showUserPro = function() {
$ionicLoading.show();
// Here i need the value of <p tag>
var name = document.getElementById("txtFirstName"),
firstNameFromHtmlPtag = name.innerText;
console.log(firstNameFromHtmlPtag, 'Doing API Call 1');
}
I tried to load a dropdown with the response got from http post. But its failing to load on child tabs.
When i click next button from tab1. I make a post call and get a JSON back. Using the returned data i want to load a dropdown in my second tab.
I already raised a query on tabset and it worked fine. Now I modified the plunker little bit. I did the same way mentioned in the below link. But i'm missing something when i try to do the samething with $http.get
Tabset $rootScope scope not updating
app.js
angular.module('plunker', ['ui.bootstrap'])
.service('Common', function() {
this.tabData = {};
})
.controller('SampleController', function($scope, $http, Common) {
$scope.submitTab1 = function() {
$http.get("post.json", {
// Some logic
}).success(function(data) {
Common.tabData = data;
$scope.steps.step2 = true;
});
}
})
.controller("SampleTab2Controller", function($scope, Common) {
$scope.userList = Common.tabData;
});
Html
<tabset ng-init="steps={step1:true, step2:false}">
<tab heading="Step 1" active="steps.step1">
<div data-ng-controller="SampleController">
<form data-ng-submit="submitTab1()">
<label>Some Operations ...</label>
<br>
<br>
<label>Click next to retrieve json from server ...</label>
<button type="submit">Click Next</button>
</form>
</div>
</tab>
<tab heading="Step 2" active="steps.step2">
<div data-ng-controller="SampleTab2Controller">
<form name="step2">
<p>load the json list from Tab1 controller </p>
<select ng-model="selectedUser" ng-options="user.title for user in userList">
<option value="">--- select ---</option>
</select>
</form>
</div>
</tab>
</tabset>
Post.json
[
{
"id": 1,
"title": "Arnold"
},
{
"id": 2,
"title": "stallone"
}
]
Plunker Code http://plnkr.co/edit/EZC1d6tDDZlpWZUHY6os?p=preview
Your issue has nothing to do with loading from http, but it has to do with properly copying reference of objects.
When you do $scope.userList = Common.tabData; the reference of tabData is copied to userList, and then when the tabData is updated using Common.tabData = data now tabData in the service points to a different reference and $scope.userList keeps pointing to the old one. So instead of getting the reference of tabData and copying it to the userList, set up the service object itself on the scope.
In your controller change $scope.userList = Common.tabData to $scope.userList = Common :-
.controller("SampleTab2Controller", function($scope, Common) {
$scope.userList = Common;
});
and in the view iterate upon userList.tabData
<select ng-model="selectedUser" ng-options="user.title for user in userList.tabData">
Plnkr
If I modified your code this way it works
1) changed tabData to be an array
2) Used angular.copy instead of asignning
.service('Common', function() {
this.tabData = []; ==> Changed this to array
})
$http.get("post.json", {
// Some logic
}).success(function(data) {
angular.copy(data,Common.tabData); ==> Used angular copy so it copies the array
$scope.steps.step2 = true;
});
Updated Plnkr
main issue in your code is controller get executed first and then Common.tabData is loaded.so can do like this:
angular.module('plunker', ['ui.bootstrap'])
.service('Common', function() {
this.tabData = {};
})
.controller('SampleController', function($scope,$http, Common) {
$scope.submitTab1 = function() {
$http.get("post.json", {
// Some logic
}).success(function(data) {
Common.tabData = data;
$scope.steps.step2 = true;
});
}
})
.controller("SampleTab2Controller", function($scope, Common) {
$scope.userList = Common;
});
and html code according to this is:
<div data-ng-controller="SampleTab2Controller">
<form name="step2">
<p>load the json list from Tab1 controller </p>
<select ng-model="selectedUser" ng-options="user.title for user in userList.tabData">
<option value="">--- select ---</option>
</select>
</form>
</div>