I am new to Angular and struggling with ng-click inside ng-repeat. For some reason, it only fires once, and the following clicks throw the following error:
Controller:
(function ( window, angular ) {
'use strict'
var LeadsController = function ( $scope, $http, $cookies, breadcrumbFactory ) {
$scope.leads = []
$scope.activeLead = undefined
$scope.breadcrumb = breadcrumbFactory
$scope.getLeads = function () {
$http({
method: 'GET',
url: '/admin/leads'
})
.success( function getLeadsSuccess ( data ) {
$scope.leads = data.data
$scope.activeLead = $scope.leads[0]
})
.error( function getLeadsError ( err ) {
console.error( err )
})
}
$scope.activateLead = function () {
$scope.activeLead = this.lead
}
$scope.getLeads()
}
angular
.module( 'app' )
.controller( 'LeadsController', [
'$scope',
'$http',
'$cookies',
'breadcrumbFactory',
LeadsController
])
})( window, angular );
HTML:
<ul class="list list--dual-line" id="leads-list">
<li ng-repeat="lead in leads">
<a ng-click="activateLead()">
<p>{{ lead.firstName }} {{ lead.lastName }}</p>
<small>{{ lead.email }}</small>
</a>
</li>
</ul>
In this code you're replacing the function activateLead with the lead that's being clicked:
$scope.activateLead = function ( lead ) {
debugger
$scope.activateLead = lead
}
Not sure what this line is supposed to do but this is the problem:
$scope.activateLead = lead
Controller:
$scope.activateLead = function(lead) {
$scope.activeLead = lead;
};
HTML:
<ul class="list list--dual-line" id="leads-list">
<li ng-repeat="lead in leads">
<a ng-click="activateLead(lead)">
<p>{{ lead.firstName }} {{ lead.lastName }}</p>
<small>{{ lead.email }}</small>
</a>
</li>
</ul>
Verify function:
$scope.activateLead = function ( lead ) {
debugger
$scope.activeLead = lead
}
the variable name is wrong!
Related
I'm new to Ionic. I write code for list. List is working perfectly but when click on any list-item it's not showing any data.
It showing me this error "Cannot GET /pilliondetails/1" how can i solve this?
app.factory('myService', function() {
var savedData = {}
function set(data) {
savedData = data;
console.log(savedData);
}
function get() {
return savedData;
}
return {
set: set,
get: get
}
})
PillionList Controller:
.controller('PillionListCtrl',function($scope,$ionicHistory,myService){
$scope.myGoBack = function() {
$ionicHistory.goBack();
};
$scope.pillions = [];
var promise=myService.get();
$scope.pillions=myService.get();
})
PillionDetail Controller:
.controller('PillionDetailCtrl',function($scope, $ionicHistory, $stateParams, myService)
{
$scope.myGoBack = function() {
$ionicHistory.goBack();
};
var promise=myService.get($stateParams.requestId);
console.log(promise);
})
PillionList.html :Showing list pf Pillions
<ion-list>
<ion-item data-ng-repeat="pillion in pillions">
<div class="list list-inset">
{{pillion.request_departure_date}}-{{pillion.request_departure_time}}
{{pillion.request_from}} >> {{pillion.request_to}}
{{pillion.user_first_name}} {{pillion.user_last_name}}
<a ui-sref="pilliondetails({pillionId:pillion.request_id})" nav-direction="enter">
<h2>More Details...</h2>
</a>
</div>
</ion-item>
</ion-list>
my app.js
.state('pillionlist', {
url: '/pillionlist',
templateUrl: 'templates/pillionlist.html',
controller: 'PillionListCtrl'
})
.state('pilliondetails', {
url: '/pillionlist/:pillionId',
templateUrl: 'templates/pilliondetails.html',
controller: 'PillionDetailCtrl'
})
Its redirecting to pillionDetail view but not showing data.
Please help.
The first thing i noticed is
ui-sref="pilliondetails({pillion.request_id})"
it should be key-value pair like this
ui-sref="pilliondetails({ your_id : pillion.request_id})"
and in stateProvider, the url of details page should contain parameter. for eg.
url : '/pilliondetails/:your_id'
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 have a simple directive that loads comments from a service(commentsService):
'use strict';
angular.module('mean.rank')
.directive('commentList', function(CommentsService, Global) {
return {
restrict: 'E',
templateUrl: 'rank/views/comments-list.html',
replace: false,
link: function($scope, element, attrs) {
//accessing the ad info : console.log("ADD " , $scope.ad);
$scope.comments = [];
$scope.loadComments = function () {
console.log("in loadComments");
var adID = {};
adID.ad_ID = $scope.ad.nid;
console.log("calling services.getComments function with " , adID.ad_ID);
CommentsService.getComments(adID.ad_ID)
.then(function (response) {
angular.forEach(comment in response)
$scope.comments.push(comment);
});
};
}
}
})
The loaded comments should be loaded to the list(inside the templateUrl) using ng-init and then the service for loading (I will add the code if needed).
<div ng-init="loadComments()">
<ul class="media-list comment-detail-list" >
<li class="media" ng-repeat="comment in comments" >
<article>
<div class="pull-left comment-info">
{{ comment.author }}<br />
<time>{{ comment.datePublished | date:"MM/dd/yyyy" }}</time>
</div>
<div class="media-body">
<div class="comment-body">
<p>{{ comment.comment }}</p>
</div>
</div>
</article>
</li>
<li>Debugger</li>
</ul>
</div>
The directive has in its scope the loadCommets() function but it is not triggered.
Thank's for your help!
I'd suggest putting the function call inside the link function itself instead of ng-init.
angular.module('mean.rank')
.directive('commentList', function(CommentsService, Global) {
return {
...
link: function($scope, element, attrs) {
//accessing the ad info : console.log("ADD " , $scope.ad);
$scope.comments = [];
$scope.loadComments = function () {
...
};
$scope.loadComments();
}
}
})
Edit: by the way your forEach syntax is wrong. It should be
angular.forEach(response, function(comment){
$scope.comments.push(comment);
});
I am building a hacker news client using the official hacker news firebase api and angular.js. I am having an issue loading the 'jobstories' posts. The id's of the stories are logged to the console, however, nothing is rendering on the screen. My code works when getting 'topstories', 'maxitem', and 'showstories', though so I'm fairly puzzled. Here is a link to the plunker.
angular.module('app.services', ['ngColorThis', 'ngTouch']).factory('HackerNews', function() {
return new Firebase('https://hacker-news.firebaseio.com/v0');});
angular.module('app.controllers', ['app.services']).controller('AppController', [
'$scope', '$sce', '$timeout', '$window', '$q', 'HackerNews', function($scope, $sce, $timeout, $window, $q, HackerNews) {
$scope.section = 'top';
$scope.gotoStory = function(story) {
$scope.currentStory = story;
$scope.storyUrl = $sce.trustAsResourceUrl(story.url);
return $scope.navi.pushPage(cordova.ThemeableBrowser.open(story.url, '_blank', {toolbar: {
height: 44,
color: 'transparent'
}, closeButton: {
image: 'ic_cancel_black',
imagePressed: 'close_pressed',
align: 'left',
event: 'closePressed'
}}));
};
$scope.loadUrl = function(url) {
return $window.open(url, '_blank', 'location=yes');
};
return $scope.getStory = function(id) {
var deferred, timer;
deferred = $q.defer();
timer = $timeout(deferred.resolve, 1000);
HackerNews.child("item/" + id).once('value', function(data) {
var item;
item = data.val();
if (item && item.type === 'story' && !item.deleted && item.url) {
$timeout.cancel(timer);
return deferred.resolve(item);
} else {
$timeout.cancel(timer);
return deferred.resolve();
}
});
return deferred.promise;
};
}
]).controller('JobController', [
'$scope', '$q', 'HackerNews', function($scope, $q, HackerNews) {
$scope.stories = [];
$scope.getJobStories = function() {
return HackerNews.child('jobstories').once('value', function(data) {
var i, id, jobId, len, promises;
console.log(data.val());
jobId = data.val();
promises = [];
for (i = 0, len = jobId.length; i < len; i++) {
id = jobId[i];
promises.push($scope.getStory(id));
}
return $q.all(promises).then(function(stories) {
stories = stories.filter(function(story) {
return typeof story !== 'undefined';
});
if (stories.length > 0) {
return $scope.stories = stories;
}
});
});
};
return HackerNews.child('jobstories').on('value', $scope.getJobStories);
}
]);
<ons-template id="jobs.html">
<ons-navigator var="navi">
<ons-list ng-controller="JobController">
<ons-list-item modifier="tappable" ng-repeat="story in stories" ng-click="gotoStory(story); showme=true;">
<div ng-hide="showme">
<div style="padding: 0 10px 0 10px;">
<span color-this="color" data-color="story.title" class="story-title">{{ story.title }}</span>
<span color-this="color" data-color="story" class="story-site">({{ story.url | urlToHost }})</span>
<span style="display:inline" class="story-info">{{ story.score }} points by</span><span style="display:inline" color-this="color" data-color="story.title" class="story-info"> {{ story.by }} </span><span style="display:inline" class="story-info">{{ story.time | timeAgo }}</span>
</div>
</div>
<div ng-show="showme" style="opacity:0.4" color-this="background" data-color="story.title">
<div style="padding: 0 10px 0 10px;">
<span class="story-title">{{ story.title }}</span>
<span color-this="color" data-color="story" class="story-site">({{ story.url | urlToHost }})</span>
<span class="story-info">{{ story.score }} points by {{ story.by }} {{ story.time | timeAgo }}</span>
</div>
</div>
</ons-list-item>
</ons-navigator>
</ons-template>
Ok I've figured out what was wrong. I had the line if (item && item.type === 'story' && !item. DELETED&& item.url) in which I limited the results to items of the type "story." The jobs posts actually have a type equal to "job" so these posts were not being allowed. I removed the condition specifying item type and was able to render the job posts to the screen.
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);
})