AngularJS - Refresh ngRepeat Array Data at Event - javascript

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

Related

input value returns NaN on ng-click

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

My ng-click is not firing

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.

How to trigger click in ng-repeat in angular js?

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?

angularjs and scope issues (I think)

I am new to angular and I have been trying to make a pretty advanced directive.
Most of the directive works, but there are two issues presenting themselves currently and I think they are both related to the scope.
Here is my directive:
angular.module('test')
.directive('testKitDesigner', function () {
panels = [];
function bindEvents() {
console.log("bindingEvents");
var styledElements = ["piping", "panel-1", "panel-2", "panel-3", "panel-4", "panel-5", "panel-6", "panel-7", "panel-8", "panel-9", "panel-10"];
for (var i = 0; i < styledElements.length; i++) {
var target = document.getElementById(styledElements[i]);
console.log(target);
if (target) {
bindEvent(target);
}
}
};
function bindEvent(target) {
console.log(target);
target.bindEvent("ngClick", selectPanel);
};
function selectPanel(event) {
var path = angular.element(event.target);
panels = []; // Reset
if (attrs.testKitDesigner && attrs.testKitDesigner === 'advanced') {
panels.push(path);
} else {
var parent = path.parent();
var paths = parent.children();
for (var i = 0; i < paths.length; i++) {
var current = angular.element(paths[i]);
var tag = current[0].nodeName;
if (tag === 'path' || tag === 'polyline') {
panels.push(current);
}
}
console.log(panels.length);
}
};
return {
restrict: 'A',
templateUrl: 'Views/Templates/designer.html',
link: function (scope, element, attrs) {
scope.step = 0;
scope.sport = 'General';
scope.garment = 'Dress';
scope.design = 'Angelus';
scope.nextStep = function () {
scope.step++;
};
scope.setSport = function (sport) {
scope.sport = sport;
scope.setSvg();
scope.nextStep();
};
scope.setGarment = function (garment) {
scope.garment = garment;
scope.setSvg();
scope.nextStep();
};
scope.setDesign = function (design) {
scope.design = design;
scope.setSvg();
scope.nextStep();
};
scope.setSvg = function () {
var children = element.children();
var template = scope.sport + '/' + scope.garment + '/' + scope.design;
for (var i = 0; i < children.length; i++) {
var child = angular.element(children[0]);
if (child.hasClass('base')) {
child.attr('test-svg', template);
bindEvents();
return;
}
}
}
scope.setColor = function (color) {
for (var i = 0; i < panels.length; i++) {
var panel = angular.element(panels[i]);
var parent = panel.parent();
if (parent.attr('id') === 'piping') {
panel.css({
'stroke': color
});
} else {
panel.css({
'fill': color
});
}
}
};
scope.init = function () {
bindEvents();
};
scope.init(); // Set our defaults;
}
}
})
.directive('testSvg', function () {
return {
restrict: 'A',
link: function (scope, element, attrs) {
scope.contentUrl = 'Views/Templates/' + attrs.testSvg + '.svg';
attrs.$observe('testSvg', function () {
console.log(attrs.testSvg);
scope.contentUrl = 'Views/Templates/' + attrs.testSvg + '.svg';
});
},
template: '<div ng-include="contentUrl"></div>'
};
});
And the designer template looks like this:
<div class="base" test-svg="/General/Polo/Angelus">
</div>
<div class="options">
<h1>Simple kit designer</h1>
<div ng-hide="step != 0">
<p>Choose your sport.</p>
<ul class="list-unstyled">
<li><a href ng-click="setSport('Netball');">Netball</a></li>
<li><a href ng-click="setSport('General');">General</a></li>
</ul>
</div>
<div ng-hide="step != 1">
<p>Choose your garment.</p>
<ul class="list-unstyled">
<li><a href ng-click="setGarment('Dress');">Dress</a></li>
<li><a href ng-click="setGarment('Polo');">Polo</a></li>
</ul>
</div>
<div ng-hide="step != 2">
<p>Choose your design.</p>
<ul class="list-unstyled">
<li><a href ng-click="setDesign('Angelus');">Angelus</a></li>
</ul>
</div>
<div class="colors" ng-hide="step != 3">
<p>Click an area to change the colour.</p>
<ul id="colour-picker" ng-hide="!picking" class="colours">
<li><a class="colour-red" href ng-click="setColor('red');"></a></li>
<li><a class="colour-orange" href ng-click="setColor('orange');"></a></li>
<li><a class="colour-yellow" href ng-click="setColor('yellow');"></a></li>
<li><a class="colour-green" href ng-click="setColor('green');"></a></li>
<li><a class="colour-blue" href ng-click="setColor('blue');"></a></li>
<li><a class="colour-indigo" href ng-click="setColor('indigo');"></a></li>
<li><a class="colour-violet" href ng-click="setColor('violet');"></a></li>
</ul>
</div>
</div>
Now, what should happen, is that when the user selects a sport or garment or design, the test-svg attribute should change to the new values and then the relevant svg will be loaded.
The attribute does change, but the observe function never gets called. I am certain that this is something to do with the scope but I can't figure it out.
You are adding test-svg attribute during link phase of test-kit-designer. The test-svg attribute are not compiled as directive so the $observe is not triggered, read up on $compile to solve your problem.
However, I would recommend restructuring your code. Consider using test-svg in the template, exposing template from setSvg in test-kit-designer and two-way binding it to another variable in test-svg.

AngularJS - Scrolling within two containers - anchorScroll

I have a page with two columns of a fixed height. The items in each column are ng-repeated.
How can I scroll within each column to a certain id? is that possible with AngularJS?
Code
<div>
Scroll to a position
Column #: <input style="width: 20px;">
Item #: <input style="width: 20px;">
</div>
<div class='column'>Column one
<div id="col-1-{{$index}}" class='item' ng-repeat='item in itemsOne track by $index'>
{{$index}} ..... {{item}}
</div>
</div>
<div class='column'>Column two
<div id="col-2-{{$index}}" class='item' ng-repeat='item in itemsTwo track by $index'>
{{$index}} ..... {{item}}
</div>
</div>
JS:
app.controller( 'myCtrl', [ '$scope', function ( $scope ){
$scope.value = 'test';
$scope.itemsOne = [];
$scope.itemsTwo = [];
for(var i=0; i<10; i++){
$scope.itemsOne.push(makeSentence());
$scope.itemsTwo.push(makeSentence());
}
function makeSentence() {
var text = "";
var possible = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789";
for( var i=0; i < Math.random() * 200; i++ ){
for( var i=0; i < Math.random() * possible.length; i++ )
text += possible.charAt(Math.floor(Math.random() * possible.length));
text += " ";
}
//console.log(text);
return text;
}
$scope.scrollMeTo = function(column, row){
// scroll me to an area in a column
};
}] );
http://plnkr.co/edit/WYtntRagJdQoK7k6fAPc?p=preview
I changed your plunkr to make it work, there is room for a lot of improvement, but please take notice that when you need to handle things in the DOM, you must always do that using directives, as the one I made:
app.directive('autoScrollTo', function () {
return function(scope, element, attrs) {
scope.$watch(attrs.autoScrollTo, function(value) {
if (value) {
var pos = $("#" +attrs.prefixId +value, $(element)).position().top + $(element).scrollTop() - $(element).position().top;
$(element).animate({
scrollTop : pos
}, 1000);
}
});
}
});
See it running: http://plnkr.co/edit/2gb8ZdZ5DPanRBVQvTwa?p=preview
Hope that helps.

Categories

Resources