I want to trigger an event click handler in angular (click the button and trigger also the span). I tried to use nth-child selector but still no results. Any suggestions ? I tried also with jQuery selector ...
JsFiddle
<div ng-app="app" ng-controller="MainCtrl">
<h3 ng-bind="version"></h3>
<div id="wrapper">
<ul>
<li ng-repeat="item in items">
<button ng-click="forceClick(item,$index)">Click</button>
<span ng-bind='item.name' ng-click='showMsg(item.name)'></span>
</li>
</ul>
</div>
</div>
angular.module('app',[])
.controller('MainCtrl', function($scope,$timeout){
$scope.version = 'Angular 1.4.8';
$scope.items = [];
$scope.showMsg = showMsg;
$scope.forceClick = forceClick;
init();
function forceClick(item, index){
$timeout(function(){
angular.element('#wrapper ul li:eq(' + index + ') span').triggerHandler('click');
},3000);
}
function showMsg(itemName){
alert("Clicked on " + itemName);
};
function init(){
for(var i=0;i<10;i++){
$scope.items.push({
name:'item ' + i,
selected:false
});
}
}
});
Try with this controller :)
angular.module('app', []).controller('MainCtrl', function($scope, $timeout) {
$scope.version = 'Angular 1.4.8';
$scope.items = [];
$scope.showMsg = showMsg;
$scope.forceClick = forceClick;
init();
$scope.showMsg = function(itemName) {
alert("Clicked on " + itemName);
};
$scope.forceClick = function(item, index) {
console.log('I clicked !!');
};
function init() {
for (var i = 0; i < 10; i++) {
$scope.items.push({
name:'item ' + i,
selected:false
});
}
}
}
);
try to inject $scope in the controller
.controller('MainCtrl', '$scope', function($scope, $timeout) {
Any examples?
Related
I am making a small Contacts application with Bootstrap 4 and AngularJS v1.6.6.
The application simply displays an Users JSON. Since the JSON returns a large number of users, the application also has a pagination feature.
The pagination worked fine as part of the app's controller, but since I tried to turn it into a service, it does not work anymore.
See a functional version of the application, with the pagination inside the controller HERE.
The application controller:
// Create an Angular module named "contactsApp"
var app = angular.module("contactsApp", []);
// Create controller for the "contactsApp" module
app.controller("contactsCtrl", ["$scope", "$http", "$filter", "paginationService", function($scope, $http, $filter) {
var url = "https://randomuser.me/api/?&results=100&inc=name,location,email,cell,picture";
$scope.contactList = [];
$scope.search = "";
$scope.filterList = function() {
var oldList = $scope.contactList || [];
$scope.contactList = $filter('filter')($scope.contacts, $scope.search);
if (oldList.length != $scope.contactList.length) {
$scope.pageNum = 1;
$scope.startAt = 0;
};
$scope.itemsCount = $scope.contactList.length;
$scope.pageMax = Math.ceil($scope.itemsCount / $scope.perPage);
};
$http.get(url)
.then(function(data) {
// contacts arary
$scope.contacts = data.data.results;
$scope.filterList();
// Pagination Service
$scope.paginateContacts = function(){
$scope.pagination = paginationService.paginateContacts();
}
});
}]);
The service:
app.factory('paginationService', function(){
return {
paginateContacts: function(){
// Paginate
$scope.pageNum = 1;
$scope.perPage = 24;
$scope.startAt = 0;
$scope.filterList();
$scope.currentPage = function(index) {
$scope.pageNum = index + 1;
$scope.startAt = index * $scope.perPage;
};
$scope.prevPage = function() {
if ($scope.pageNum > 1) {
$scope.pageNum = $scope.pageNum - 1;
$scope.startAt = ($scope.pageNum - 1) * $scope.perPage;
}
};
$scope.nextPage = function() {
if ($scope.pageNum < $scope.pageMax) {
$scope.pageNum = $scope.pageNum + 1;
$scope.startAt = ($scope.pageNum - 1) * $scope.perPage;
}
};
}
}
});
In the view:
<div ng-if="pageMax > 1">
<ul class="pagination pagination-sm justify-content-center">
<li class="page-item"><i class="fa fa-chevron-left"></i></li>
<li ng-repeat="n in [].constructor(pageMax) track by $index" ng-class="{true: 'active'}[$index == pageNum - 1]">
{{$index+1}}
</li>
<li><i class="fa fa-chevron-right"></i></li>
</ul>
</div>
The service file is included in the project (correctly, in my opinion) after the app.js file:
<script src="js/app.js"></script>
<script src="js/paginationService.js"></script>
I am not an advanced AngularJS user so I don't know: what is missing?
It appears that the service needs to be defined before the controller, otherwise it cannot be injected properly.
So you could either move the paginationService into app.js:
var app = angular.module("contactsApp", []);
app.factory('paginationService', function(){
//...
});
app.controller("contactsCtrl", ["$scope", "$http", "$filter", "paginationService", function($scope, $http, $filter) {
//...
});
Or else move the controller out to a separate file that is included after the paginationServices.js file.
Take a look at this plunker. Try modifying line 6 - remove character 5, i.e. the space that separates the star and slash that would close the multi-line comment.
I am writing a program that takes in input value for two numbers and provides a random value from the range specified. I have fixed controllers to shuffle min and max value and it works once i place numbers but if i add the ng-model value, it returns "NaN". Here is the html
<div class="col-sm-4" ng-controller="ValueController">
<div class="row">
<div class="col-sm-6"><input type="number" ng-model="value.one">
</div>
<div class="col-sm-6"><input ng-model="value.two"></div>
</div>
</div>
<div class="col-sm-4">
<a ng-href="results.html" ng-controller="ShuffleController"
ng-click="shuffle(100100, 110000)">
<img src="img/before.png" style="width: 500px; height: auto;"></a>
</ul>
</div>
Here is part of the app.js:
// Angular App Initialization
var app = angular.module('Shuffle', ['ngRoute']);
// Declaring Globals
app.run(function($rootScope) {
$rootScope.shuffled = [];
$rootScope.shuffleValues = {};
$rootScope.getRand = function(min, max) {
var number = Math.floor(Math.random() * (max - min)) + min;
var leadingZeroes = 6 - number.toString().length;
$rootScope.shuffled.push([[min, max], number.toString().length < 6 ? ('0'.repeat(leadingZeroes) + number) : number]);
window.localStorage.setItem('shuffled', JSON.stringify($rootScope.shuffled));
}
});
// Shuffle Controller
app.controller('ShuffleController', function($scope, $rootScope, $window) {
console.log('Welcome to TheShuffler!');
var results = window.localStorage.getItem('shuffled');
results = JSON.parse(results);
$scope.shuffle = function(min, max) {
console.log("You shuffled!");
console.log(results);
$rootScope.getRand(min, max);
}
});
// Results Controller
app.controller('ResultsController', function($scope) {
var results = window.localStorage.getItem('shuffled');
$scope.shuffleResults = JSON.parse(results);
$scope.quantity = 3;
console.log($scope.shuffleResults);
});
// Reshuffling Controller
app.controller('ReshuffleController', function($scope, $rootScope, $route, $window, $location) {
$scope.reshuffle = function(){
$window.location.reload();
console.log('You reshuffled!');
var results = window.localStorage.getItem('shuffled');
results = $scope.shuffleResults = JSON.parse(results);
for (var i = 0; i < results.length; i++) {
var min = results[i][0][0]
var max = results[i][0][1]
$rootScope.getRand(min, max)
}
}
});
// Shuffle Entries Verification Controller
app.controller('ShuffleEntriesVerificationController', function($scope, $window) {
console.log('EntriesHere!');
$scope.entryCheck = function(){
var results = window.localStorage.getItem('shuffled');
results = JSON.parse(results);
console.log("You checked!");
console.log(results);
var verficationMessage = "Maximum Entries Exceeded. Please Click Shuffle";
if (results.length > 2) {
$window.alert(verficationMessage);
$window.location.reload();
}
}
});
app.controller('ValueController', ['$scope', function($scope) {
$scope.value = {
one: 000100,
two: 005100
};
}]);
it('should check ng-bind', function() {
var nameInput = element(by.model('value'));
expect(element(by.binding('value')).getText()).toBe('Whirled');
nameInput.clear();
nameInput.sendKeys('world');
expect(element(by.binding('value')).getText()).toBe('world');
});
I get NaN when i do this:
<a ng-href="results.html" ng-controller="ShuffleController"
ng-click="shuffle(value.one, value.two)">
<img src="img/before.png" style="width: 500px; height: auto;"></a>
What is the problem?
You have a wrong controller:
ng-controller="ShuffleController"
while in your app you have this controller:
app.controller('ValueController',...
...
}]);
You don't have to pass the model as parameter values will be automatically bound and available in your shuffle function.
In case of your NaN error create a snippet to get a better perspective of your problem
I'm new to Angular, so please bear with me.
I have an app I'm building where you can hit an "X" or a heart to dislike/like something. I'm using a swipe library called ng-swippy.
I'm trying to use ng-click="clickLike()"for the "Like" button and ng-click="clickDislike()"but neither are firing. I can't figure out what's going on.
Here's the URL:
http://430designs.com/xperience/black-label-app/deck.php
deck.php code
<ng-swippy collection='deck' item-click='myCustomFunction'
data='showinfo' collection-empty='swipeend' swipe-left='swipeLeft'
swipe-right='swipeRight' cards-number='4' label-ok='Cool'
label-negative='Bad'>
</ng-swippy>
The template is called from card-tpl.html:
<div class="ng-swippy noselect">
<div person="person" swipe-directive="swipe-directive" ng-repeat="person in peopleToShow" class="content-wrapper swipable-card">
<div class="card">
<div style="background: url({{person.thumbnail}}) no-repeat 50% 15%" class="photo-item"></div>
<div class="know-label">{{labelOk ? labelOk : "YES"}}</div>
<div class="dontknow-label">{{labelNegative ? labelNegative : "NO"}}</div>
</div>
<div class="progress-stats" ng-if="data">
<div class="card-shown">
<div class="card-shown-text">{{person.collection}}</div>
<div class="card-shown-number">{{person.subtitle}}</div>
</div>
<div class="card-number">{{collection.length - (collection.indexOf(person))}}/{{collection.length}}
</div>
</div>
<div class="container like-dislike" >
<div class="circle x" ng-click="clickDisike()"></div>
<div class="icon-like" ng-click="clickLike()"></div>
<div class="clearfix"></div>
</div>
</div><!-- end person-->
<div class="clearfix"></div>
Controller.js
angular.module('black-label', ['ngTouch', 'ngSwippy'])
.controller('MainController', function($scope, $timeout, $window) {
$scope.cardsCollection = [
{
thumbnail: 'images/deck/thor_01.jpg',
collection: 'thoroughbred',
}, {
thumbnail: 'images/deck/thor_02.jpg',
collection: 'thoroughbred',
},
];
// Do the shuffle
var shuffleArray = function(array) {
var m = array.length,
t, i;
// While there remain elements to shuffle
while (m) {
// Pick a remaining element
i = Math.floor(Math.random() * m--);
// And swap it with the current element.
t = array[m];
array[m] = array[i];
array[i] = t;
}
return array;
};
$scope.deck = shuffleArray($scope.cardsCollection);
$scope.myCustomFunction = function(person) {
$timeout(function() {
$scope.clickedTimes = $scope.clickedTimes + 1;
$scope.actions.unshift({ name: 'Click on item' });
$scope.swipeRight(person);
});
};
$scope.clickLike = function(person) {
console.log($scope.count);
// swipeRight(person);
};
$scope.count = 0;
$scope.showinfo = false;
$scope.clickedTimes = 0;
$scope.actions = [];
$scope.picks = [];
var counterRight = 0;
var counterLeft = 0;
var swipes = {};
var picks = [];
var counts = [];
var $this = this;
$scope.swipeend = function() {
$scope.actions.unshift({ name: 'Collection Empty' });
$window.location.href = 'theme-default.html';
};
$scope.swipeLeft = function(person) {
//Essentially do nothing
$scope.actions.unshift({ name: 'Left swipe' });
$('.circle.x').addClass('dislike');
$('.circle.x').removeClass('dislike');
$(this).each(function() {
return counterLeft++;
});
};
$scope.swipeRight = function(person) {
$scope.actions.unshift({ name: 'Right swipe' });
// Count the number of right swipes
$(this).each(function() {
return counterRight++;
});
// Checking the circles
$('.circle').each(function() {
if (!$(this).hasClass('checked')) {
$(this).addClass('checked');
return false;
}
});
$('.icon-like').addClass('liked');
$('.icon-like').removeClass('liked');
$scope.picks.push(person.collection);
// console.log('Picks: ' + $scope.picks);
// console.log("Counter: " + counterRight);
if (counterRight === 4) {
// Calculate and store the frequency of each swipe
var frequency = $scope.picks.reduce(function(frequency, swipe) {
var sofar = frequency[swipe];
if (!sofar) {
frequency[swipe] = 1;
} else {
frequency[swipe] = frequency[swipe] + 1;
}
return frequency;
}, {});
var max = Math.max.apply(null, Object.values(frequency)); // most frequent
// find key for the most frequent value
var winner = Object.keys(frequency).find(element => frequency[element] == max);
$window.location.href = 'theme-' + winner + '.html';
} //end 4 swipes
}; //end swipeRight
});
Any thoughts and help is greatly appreciated!
The ng-click directive is inside an ng-repeat directive inside a directive with isolate scope. To find the clickLike() function it needs to go up two parents:
<!--
<div class="icon-like" ng-click="clickLike()"></div>
-->
<div class="icon-like" ng-click="$parent.$parent.clickLike()"></div>
For information, see AngularJS Wiki - Understanding Scopes.
Why in this jsfiddle $scope.counter inside ChildController3 do not resolve to ParenctController's $scope.counter but creates a counter on local $scope?
Replicating Code:
HTML
<div ng-app='app'>
<div ng-controller="ParentController">
<h2>ChildController1</h2>
<div ng-controller="ChildController1">
<button ng-click="add()">Add</button>
<button ng-click="subtract()">Subtract</button>
</div>
<h2>ChildController2</h2>
<div ng-controller="ChildController2">
<button ng-click="add()">Add</button>
<button ng-click="subtract()">Subtract</button>
<br/>
{{ counter }} <- this is in local scope
</div>
{{ counter }} <- this is in parent scope
<h2>ChildController3</h2>
<div ng-controller="ChildController3">
<button ng-click="add()">Add</button>
<button ng-click="subtract()">Subtract</button>
<br/>
{{ counter }} <- this is in local scope
</div>
</div>
</div>
JS
var app = angular.module("app",[]);
app.controller('ParentController', function($scope)
{
$scope.counter = 5;
});
app.controller('ChildController1', function ($scope) {
$scope.add = function () {
$scope.counter += 1;
};
$scope.subtract = function () {
$scope.counter -= 1;
};
});
app.controller('ChildController2',function($scope) {
$scope.add = function () {
$scope.$parent.counter += 1;
};
$scope.subtract = function () {
$scope.$parent.counter -= 1;
};
});
app.controller('ChildController3', function($scope) {
$scope.add = function () {
$scope.counter += 1;
};
$scope.subtract = function () {
$scope.counter -= 1;
};
});
Its because the scopes of different levels in the hierarchy share scope using prototypical inheritance.
A pure JS example would be:
function A(){
this.count = 5;
}
function B(){
}
a = new A();
B.prototype = a;
b = new B();
console.log(a.count,b.count); // gives 5 5 <--- shared
a.count++;
console.log(a.count,b.count); // give 6 6 <----- still shared
b.count++;
console.log(a.count,b.count); // gives 6 7 <----- link broken
a.count++;
The link is broken because after "b.count++;" b really has a count property, before that it was just a prototype property.
More info on this can be found here: Angular scope docs
try this:
<div ng-app='app'>
<div ng-controller="ParentController">
<h2>ChildController1</h2>
<div ng-controller="ChildController1">
<button ng-click="add()">Add</button>
<button ng-click="subtract()">Subtract</button>
</div>
<h2>ChildController2</h2>
<div ng-controller="ChildController2">
<button ng-click="add()">Add</button>
<button ng-click="subtract()">Subtract</button>
<br/>
{{ number.counter }} <- this is in local scope
</div>
{{ number.counter }} <- this is in parent scope
<h2>ChildController3</h2>
<div ng-controller="ChildController3">
<button ng-click="add()">Add</button>
<button ng-click="subtract()">Subtract</button>
<br/>
{{ number.counter }} <- this is in local scope
</div>
</div>
</div>
var app = angular.module("app",[]);
app.controller('ParentController', function($scope)
{
$scope.number = {};
$scope.number.counter = 5;
});
app.controller('ChildController1', function ($scope) {
$scope.add = function () {
$scope.number.counter += 1;
};
$scope.subtract = function () {
$scope.number.counter -= 1;
};
});
app.controller('ChildController2',function($scope) {
$scope.add = function () {
$scope.$parent.number.counter += 1;
};
$scope.subtract = function () {
$scope.$parent.number.counter -= 1;
};
});
app.controller('ChildController3', function($scope) {
$scope.add = function () {
$scope.number.counter += 1;
};
$scope.subtract = function () {
$scope.number.counter -= 1;
};
});
This happens because you´re overwriting your $scope.counter inside 'ChildController3'.
here, see this video at 30 min to see a better explanation about this:
AngularJS MTV Meetup: Best Practices
What happened here to make it work was because you declared "$scope.number = {};" inside "ParentController", so when you use it "$scope.number.counter" inside "ChildController3" you made a reference to ParentController instead of before when you just overwrote "$scope.counter" inside of "ChildController3".
I'm migrating my jQuery app to AngularJS.
What I need to do, is change the Data Array when a scroll occurred, how can i do this?
I have this code with jQuery at plunk:
http://plnkr.co/edit/jdwxH5pmyecuWTsrutrO?p=preview
When you scroll the div, a list with the visible elements index is show.
What I want to do, is to set a directive or a filter (ng-check-visibility) at the ng-repeat element, like:
<div ng-repeat="item in data" ng-check-visibility>
{{item.name}}
</div>
And this directive change the item setting the value item.visible=true when the element is visible, otherwise, set it to false.
Can I do this with Angular? Any ideas?
Here's a way to do it as a directive:
var app = angular.module('myapp', []);
app.controller('MainCtrl', function($scope) {
arr = [];
for(var i=0; i<500; i++){
arr.push({id: i, name: 'name'+i});
}
$scope.data = {
items: arr,
visible: []
};
});
app.directive('checkVisibility', function() {
return {
scope: {
data: '=checkVisibility'
},
link: function(scope, el, attrs) {
el.scroll( function() {
var reference_top = el.offset().top;
var reference_height = el.height();
var $elements = el.find('.check');
scope.data.visible = [];
for(var i=0; i<$elements.length; i++){
var $element = $($elements[i]);
var element_top = $element.offset().top;
var element_height = $element.height();
if (reference_top < element_top + element_height &&
reference_top + reference_height > element_top) {
scope.data.visible.push( i );
}
}
scope.$apply();
});
}
};
});
--
<body ng-controller="MainCtrl">
<div class="outer-panel" check-visibility="data">
<div class="inner-panel">
<div ng-repeat="item in data.items" class="check">
{{item.name}}
</div>
</div>
</div>
<div id="visibles">
{{data.visible}}
</div>
</body>
plunkr