I am a new AngularJS learner.
My code is calling a JSON file and displays the output. However, I want the call to change the JSON call based on change in certain variable (i.e. KeyWord).
Here is the HTML part:
<body ng-controller="AppController">
<button type="button" class="btn btn-danger" ng-click="ChangeKW()">
Click to Change KeyWord
</button>
<div ng-controller="customersController as custCont" ng-model="keyWord">
KeyWord:{{ keyWord }} ==== iter:{{ iter }}
<ul>
<li ng-repeat="x in names">
{{ x.Name + ', ' + x.Country }}
</li>
</ul>
</div>
</body>
And here goes the Controller part:
var app = angular.module('App', []);
app.controller('AppController', function($scope, $window) {
$scope.keyWord = 3;
$scope.iter = 1;
$scope.ChangeKW = function() {
if ( $scope.keyWord === 3 )
$scope.keyWord = 1;
else
$scope.keyWord = $scope.keyWord + 1;
}
});
app.controller("customersController", function($scope, $http) {
$scope.iter = $scope.iter + 1;
$http({
url: 'test' + $scope.keyWord + '.txt',
dataType: 'json',
method: 'GET',
data: '',
headers: {
"Content-Type": "application/json"
}
}).success(function(response) {
$scope.names = response;
}).error(function(error) {
$scope.names = [{
"Name": "Errrrrrr"
}];
});
});
I want the program to load respective JSON file text1.txt, text2.txt or text3.txt based on value of KeyWord variable, which can be changed by clicking on the red button. I have defined mg-model="KeyWord" in HTML, which changes the value of {{ KeyWord }} in the output but it doesn't send refresh JSON call/output. The initial file loaded is tex3.txt (all three files can be distinguished from 1st record).
The Plunker can be found here: Plunker.
you probably need:
$scope.$watch('keyWord',function()
{
//$http call here
}
);
the ‘$watch‘ will make the $http call automatically, each time $scope.keyWord changes.
(Posted on behalf of the question author).
Here is the final solution that I found out with the help of #Manube:
HTML
<body ng-controller="AppController">
<button type="button" class="btn btn-danger" ng-click="ChangeKW()">
Click to Change KeyWord
</button>
<div ng-controller="customersController as custCont" ng-model="keyWord">
KeyWord:{{ keyWord }} ==== iter:{{ iter }}
<ul>
<li ng-repeat="x in names">
{{ x.Name + ', ' + x.Country }}
</li>
</ul>
</div>
</body>
This is the Controller code
(function() {
var app = angular.module('App', []);
app.controller('AppController', function($scope, $window,$http) {
$scope.keyWord = 3;
$scope.iter = 1;
$scope.ChangeKW = function() {
if ($scope.keyWord >2)
$scope.keyWord = 1;
else
$scope.keyWord = $scope.keyWord + 1;
};
$scope.loadData = function() {
$scope.iter = $scope.iter + 1;
$http({
url: 'test' + $scope.keyWord + '.txt',
dataType: 'json',
method: 'GET',
data: '',
headers: {
"Content-Type": "application/json"
}
}).success(function(response) {
$scope.names = response;
}).error(function(error) {
$scope.names = [{
"Name": "Errrrrrr"
}];
});
};
$scope.$watch('keyWord', function() {
$scope.loadData();
});
$scope.customersController = function($scope, $http) {
$scope.loadData();
};
});
})();
And a working Plunker can be found here: Plunker Link
Related
Hi I am new to Angularjs. I am trying to create a typeahead where I am fetching the data through the api. I tried searching for the solution but I dint get the solution what I was looking for. Below is the code what I have done so far.
HTML CODE:
<div ng-controller="newController">
<div class="selection-box">
<div class="title-box">
<div class="search_item">
<input name="document" ng-model='query' type="text" typeahead="document as document.name for document in documents | filter:query | limitTo:8" id='document' placeholder="SEARCH FOR YOUR DOCUMENT" class="search_box">
</div>
{{query}}
</div>
</div>
</div>
In this input box whatever I type it gets printed in the {{query}} but doesn't show any data fetching from the api. I am using bootstrap ui . Below is the controller what I wrote.
newController.js:
var myApp = angular.module('myModule', ['ui.bootstrap']);
myApp.service("searchService", function ($http) {
var apiUrl = "http://12.56.677/api/v1/mobile/";
var apiKey = "123nm";
this.searchDocument = function(query) {
var response = $http({
method: 'post',
url: apiUrl + "search",
headers: {'Content-Type': 'application/x-www-form-urlencoded; charset=UTF-8'},
params: {
key: apiKey,
query: query
}
});
return response;
};
});
myApp.controller('newController', ['$scope', 'searchService' , function($scope, searchService, $rootScope, $http, $window, $document) {
var apiUrl = "http://12.56.677/api/v1/mobile/";
var apiKey = "123nm";
url = apiUrl + "search";
Key = apiKey;
$scope.query = undefined;
console.log(query);
searchService.searchDocument(query='').then (function (res) {
if(res.data.status == "OK")
{
$scope.documents = res.data.result;
console.log($scope.documents);
// var userinformation = res.data.result;
// $window.localStorageService.setItem('searchDocument', JSON.stringify(query));
}
else {
$scope.errorMessage = res.data.message;
}
})
}])
Any help would be appreciated.
What you attempted to do is using typeahead with a pre-fetched list (an with an empty query).
You probably want to do asynchronous search and would need a data fetch function to do so.
HTML, note the typeahead expression:
<input name="document" ng-model='query' type="text"
typeahead="document as document.name for document in (getDocuments() | limitTo:8)"
id='document'
placeholder="SEARCH FOR YOUR DOCUMENT" class="search_box">
Controller:
myApp.controller('newController', ['$scope', 'searchService' , function($scope, searchService, $rootScope, $http, $window, $document) {
var apiUrl = "http://12.56.677/api/v1/mobile/";
var apiKey = "123nm";
// What are these two undeclared variables lying here around for?
url = apiUrl + "search";
Key = apiKey;
$scope.getDocuments = function(query){
searchService.searchDocument(query) // Check your API, I am not sure how you're API treats these parameters
.then (function (res) {
if(res.data.status == "OK")
{
var documents = res.data.result;
console.log(documents);
return documents;
}
else {
$scope.errorMessage = res.data.message;
return [];
}
})
}
}])
I think you need to return promise from the searchService.searchDocment() as below:
return searchService.searchDocument(query='').then(......)
//HTML
<input name="document"
ng-model='query' type="text"
uib-typeahead="document as document.name
for document in documents |filter:query | limitTo:8" id='document'
placeholder="SEARCH FOR YOUR DOCUMENT" class="search_box">
//Controller
searchService.searchDocument('').then (function (res) {
if(res.data.status == "OK"){
$scope.documents = res.data.result;
}
else {
$scope.errorMessage = res.data.message;
}
});
Why after invoking English() or France() functions value of $scope.currentLanguageId in myFilter does not change?
Is it normal way to make different localization of site by filters? Or existing may be more common way?
List:
<div ng-init="GetList()">
<div ng-repeat="item in items | filter: myFilter">
{{item.Text}} {{item.LanguageId}}
</div>
</div>
Menu:
<div class="menu">
<ul>
<li>About</li>
<li>Contacts</li>
<li><a>Test</a></li>
<li><a>Test</a></li>
<li><a>Test</a></li>
<li><input type="button" value="En" ng-controller="homeController" ng-click="English()" /></li>
<!--<li><a>En</a></li>
<li><a>Fr</a></li>-->
</ul>
</div>
Controller:
app.controller('homeController', function ($scope, $http) {
$scope.items = [];
$scope.currentLanguageId = '';
$scope.GetList = function () {
$http({
method: 'GET',
url: '/Home/GetList',
params: { languageId: '1'}
}).then(function successCallback(response) {
$.each(response.data, function (id,item) {
$scope.items.push({ Text: item.Text, LanguageId: item.LanguageId });
});
}, function errorCallback(response) {
alert('Error');
});
}
$scope.English = function () {
$scope.currentLanguageId = '2';
}
$scope.France = function () {
$scope.currentLanguageId = '3';
}
$scope.myFilter = function (item) {
console.log($scope.currentLanguageId);
return item.LanguageId == $scope.currentLanguageId;
};
});
DEMO
I would create a service for that, and attach it to the $rootScope so it is available everywhere in my application and does not need to be injected in each controller
var app = angular.module('app', []);
app.run(function(langService){
langService.fetch('spanish');
});
app.controller('MainController', function(){
var vm = this;
});
app.service('langService', function($rootScope){
this.current = {};
this.fetch = function(lang){
//do your fetching here with $http
$rootScope.lang = {
ok: 'si',
yes: 'si',
no: 'no'
};
};
});
then you can use it anywhere in your app like
<button>{{$root.lang.ok}}</button>
<button>{{$root.lang.no}}</button>
Other things worth pointing out:
Your controller is too fat, you should not put logic on your controller, logic should be in services
Avoid using ng-init as much as possible, do it inside the controller
I do not know what is wrong, ng-repeat is not
populating the information on my div, please look at the following
and advice where I have gone wrong
app.js
var mainApp = angular.module('mainApp', ["ngRoute", "ngResource"]);
mainApp.factory('EventListFactory',['$resource', EventListFactory]);
mainApp.controller('EventListCtrl', ['$scope','EventListFactory', EventListCtrl]);
var configFunction = function ($routeProvider) {
$routeProvider.
when('/Register', {
templateUrl: 'routesDemo/Register'
})
.when('/UpdateProfile', {
templateUrl: 'routesDemo/UpdateProfile'
})
.when('/Events', {
templateUrl: 'routesDemo/Events',
controller: EventListCtrl,
})
.when('/routeThree', {
templateUrl: 'routesDemo/three'
});
}
configFunction.$inject = ['$routeProvider'];
mainApp.config(configFunction);
EventListFactory.js
var EventListFactory = function ($resource, $location) {
var baseUrl = "";
if (window.location.hostname == 'localhost') {
baseUrl = "http://localhost:52182/api/Events/GetEvents/";
}
else
{
var deployAt = window.location.href.substring(0, window.location.href);
baseUrl = deployAt + "/api/Events/GetEvents";
}
var respone = $resource(baseUrl, null, { query: { method: 'GET', isArray: true, url: baseUrl }, get: { method: 'GET', url: baseUrl } });
console.log("api json at :" + baseUrl);
var records = respone.query();
console.log(records);
return records;
}
EventListController.js
var EventListCtrl = function ($scope, EventListFactory) {
$scope.Message = 'I work';
$scope.items = EventListFactory;
};
EventListCtrl.$inject = ['$scope'];
in the html:
<div id="listView" >
<h1 class="form-signin-heading">For real {{Message}}</h1>
<div ng-controller="EventListCtrl">
<p class="form-signin-heading">Populated Data</p>
<div ng-repeat="item in items ">
<span class="control-label">Heading : </span> {{item.Heading}}
<br/>
<span class="control-label">Event Date : </span> {{item.EventDate}}
<br/>
</div>
</div>
</div>
running the site:
api call from browser:
the code for ng-repeat is correct, but your items is an empty array so nothing gets displayed.
From the screenshots it appears that records in EventListFactory.js does not return an array but a promise.
In EventListController.js instead of
$scope.items = EventListFactory;
Try something like:
var promise = EventListFactory;
promise.then(function(data){
$scope.items = data;
})
I have a three functions in each there is $scope.fetch() which is being called when ng-submit=fetch is pressed. I want one ng-submit button which would call all three fetch() in three functions how can I do this?
HTML:
<div type="text/ng-template" id="getnewcoolios.html" class="users">
<h1>{{message}}</h1>
<form name="myform" id="myform1" ng-submit="fetch()" >
<input type="date"
ng-model="date"
value="{{ 'date' | date: 'dd/MM/yyyy' }}" />
<div><center><button type="submit" >Fetch</button></center></div>
</form>
{{formdata.date}}
<ul ng-controller="NewCooliosCtrl" ng-repeat="newCoolio in newCoolios.newCoolios">
<li>{{newCoolio.personID}}, {{newCoolio.placeID}}, {{newCoolio.datePlaced}}</li>
</ul>
<ul ng-controller="NewPlacesCtrl" ng-repeat="newPlace in newPlaces.newPlaces">
<li>{{newPlace}} </li>
</ul>
<ul ng-controller="NewUsersCtrl" ng-repeat="newUser in newUsers.newUsers">
<li>New Users: {{newUser}} </li>
</ul>
</div>
Angular:
myApp.config(['$routeProvider',
function($routeProvider) {
$routeProvider
.when('/getdailydata', {
templateUrl: 'templates/getnewcoolios.html',
controller: 'DailyCtrl'
})
}])
.controller('DailyCtrl', function($scope) {
})
.controller('NewUsersCtrl', function($scope,$http,$filter) {
$scope.fetch= function(){
var formdata =
{'date' : $filter('date')(this.date, 'dd/MM/yyyy')
};
var inserturl = 'http://94.125.132.253:8001/getnewusers?date=' + formdata.date;
$http.get(inserturl).success(function (data) {
console.log(formdata);
$scope.newUsers = data;
console.log(inserturl);
console.log(data);
$scope.message = 'List of New Users';
})}
})
.controller('NewPlacesCtrl', function($scope,$http,$filter) {
$scope.fetch= function(){
var formdata =
{'date' : $filter('date')(this.date, 'dd/MM/yyyy')
};
var inserturl = 'http://94.125.132.253:8001/getnewplaces?date=' + formdata.date;
$http.get(inserturl).success(function (data) {
console.log(formdata);
$scope.newPlaces = data;
console.log(inserturl);
console.log(data);
$scope.message = 'List of New places';
}
)
}
})
.controller('NewCooliosCtrl', function($scope,$http,$filter) {
$scope.fetch= function(){
var formdata =
{'date' : $filter('date')(this.date, 'dd/MM/yyyy')
};
var inserturl = 'http://94.125.132.253:8001/getnewcoolios?date=' + formdata.date;
$http.get(inserturl).success(function (data) {
console.log(formdata);
$scope.newCoolios = data;
console.log(inserturl);
console.log(data);
$scope.message = 'List of New Coolios';
}
)}});
You can access outer scope properties in inner scopes, so you can define each fetch function in inner scopes and push them into array of functions to be called on submit. Then, on submit^ just iterate through that array and call each function. Voila.
<div ng-controller="fetcher">
<form name="myForm" ng-submit="fetch"></form>
<ul ng-controller="NewCooliosCtrl"></ul>
<ul ng-controller="NewPlacesCtrl"></ul>
<ul ng-controller="NewUsersCtrl"></ul>
<div>
.controller('fetcher', function($scope){
$scope.toFetch = [];
$scope.fetch = function(){
for(var i=0; i<$scope.toFetch.length; i++){
$scope.toFetch[i]();
}
}
});
.controller('NewCooliosCtrl', function($scope){
$scope.fetch= function(){...};
$scope.toFetch.push($scope.fetch);
})
.controller('NewPlacesCtrl', function($scope){
$scope.fetch= function(){...};
$scope.toFetch.push($scope.fetch);
})
.controller('NewUsersCtrl', function($scope){
$scope.fetch= function(){...};
$scope.toFetch.push($scope.fetch);
})
Below I've got an angular app and controller where the controller have data access inside of it (bad idea, I know)
var app = angular.module('app',[]);
app.controller('HomeController',function($scope,$http){
$scope.people = null;
$scope.get = function() {
$http({
url: 'largeTestData.json',
method: 'GET'
}).then(function(data){
console.log('request successful, here is your data: ');
console.log(data['data']);
$scope.people = data['data'];
},function(reason){
console.log('this failed, this is the reason: ');
console.log(reason);
})
}
});
app.controller('ControllerWithService',function($scope, MyService){
$scope.get = MyService.get;
$scope.get(function(data){
console.log('you succeeded');
},function(reason){
console.log('you failed');
console.log(reason);
})
})
This will work in retrieving data and putting it onto the page. Knowing that having data Access in the controller is no bueno I tried to abstract that out into a service:
app.service('MyService',function($http,$q){
var get = function(){
var deferred = $q.defer();
var url = 'test.json';
$http.get(url).success(deferred.resolve).error(deferred.reject);
}
return {
get: get
}
})
Here my 'data layer' is a service that only has one method: get from the above listed URL.
app.service('MyService',function($http,$q){
var get = function(){
var deferred = $q.defer();
var url = 'test.json';
$http.get(url).success(deferred.resolve).error(deferred.reject);
}
return {
get: get
}
})
and my HTML
<body>
<script src="libs/angular-1.2.15.js"></script>
<script src="app/app.js"></script>
<script src="app/DocumentService.js"></script>
<script src="libs/jQuery-2.1.1.js"></script>
<div ng-controller="HomeController">
<button ng-click="get()" href="#">Get data</button>
<div>{{message}}</div>
<!--<div ng-repeat="p in people" >-->
<!--<b>Business Doc ID: </b><h1>{{p['busDocId']}}</h1>-->
<!--<b>DOC ID: </b>{{p['docId']}}-->
<!--<b>FILE NAME: </b><div style="color: green">{{p['fileName']}}</div>-->
<!--</div>-->
</div>
<div ng-controller="ControllerWithService">
{{message}}
<button ng-click="get()">get data</button>
<div>{{data}}</div>
</div>
</body>
I'm not getting any error messages, and the commented out out stuff in my HomeController works as expected. What am I doing wrong in trying to make my AJAX calls a service?
working solution changes:
app.service('MyService',function($http,$q){
this.get = function(){
return $http.get('test.json')
}
})
app.controller('ControllerWithService',function($scope, MyService){
$scope.data = null;
$scope.get = function() {
MyService.get().then(function (data) {
console.log('this is the success data: ');
console.log(data)
$scope.data = data;
}, function (reason) {
console.log('this is the fail reason');
console.log(reason);
$scope.data = reason;
})
}
})
It looks like it could be a couple different things. I'll post an example I have working in one of my projects right now. It should be extremely similar and simple with what you're goal is.
Service:
'use strict';
angular.module('srcApp')
.service('Getlanguage', function Getlanguage($location, $http, $log, $state, $rootScope) {
this.getContent = function() {
var language = $location.path().split('/'),
languageCulture = language[1];
if (!languageCulture) {
languageCulture = 'en';
}
$rootScope.cultureCode = languageCulture;
return $http({method: 'GET', url: '/languages/' + languageCulture + '.json'})
.error(function() {
// If service cannot find language json file, redirect to index
$state.go('lang', {lang: 'en'});
});
};
});
Controller Call to service:
After passing in the service as a dependency into the controller.
Getlanguage.getContent().then(function(res) {
$scope.content = res.data;
});
Hope this helps.