Angular: ng-show one repeating element - javascript

I have a table, and each row is generated using ng-repeat. One of the columns has a refresh icon, which when clicked carries out a task. However while this task is being carried out, I'd like the icon to spin; see here.
The issue I'm having is that when I click one of the icons, they all spin, rather than the one on just that row.
<td class="text-center">
<i ng-hide="refreshUserSpin" ng-click="refreshUser($index, user.id)" class="fa fa-refresh pointer"></i>
<i ng-show="refreshUserSpin" class="fa fa-refresh fa-spin "></i>
</td>
So in my controller, I set the refreshUserSpin to false:
app.controller('usersController', function($scope, Users) {
$scope.refreshUserSpin = false;
$scope.refreshUser = function(index, community_id) {
$scope.refreshUserSpin = true;
Users.refreshUser(community_id)
.success(function(data) {
$scope.users[index] = data.json;
$scope.refreshUserSpin = false;
});
};
});
Now this sends all of the icons into a spin. What is the correct way to handle this, so it only does it for that row.
I've tried doing things like:
<i ng-show="refreshUserSpin.$index" class="fa fa-refresh fa-spin "></i>
Then doing $scope.refreshUserSpin.index = true;, but this didn't seem to work.
Any ideas?

Try this
HTML
<td class="text-center">
<i ng-hide="refreshUserSpin[$index]" ng-click="refreshUser($index, user.id)" class="fa fa-refresh pointer"></i>
<i ng-show="refreshUserSpin[$index]" class="fa fa-refresh fa-spin "></i>
</td>
JS
app.controller('usersController', function($scope, Users) {
$scope.refreshUserSpin = {};
$scope.refreshUser = function(index, community_id) {
$scope.refreshUserSpin[index] = true;
Users.refreshUser(community_id)
.success(function(data) {
$scope.users[index] = data.json;
$scope.refreshUserSpin[index] = false;
});
};
});

Related

problem in #click event which adding one more fontawesome icon

i tried to make responsive navigation with vue js, when i tried to add '#click' to toggle burger bar or close icon, but it's adding the 'close' icon instead every time i click it.
here's the code
template section
<template>
// ----
<button #click="toggleButton">
<i v-if="!toggle" class="fas fa-bars"></i>
<i v-if="!toggleClose" class="fas fa-times"></i>
</button>
// ----
</template>
script section
<script>
export default {
name: "MultiNav",
data: function() {
return {
toggle: false,
toggleClose: true
};
},
methods: {
toggleButton() {
this.toggle = !this.toggle;
this.toggleClose = !this.toggleClose;
}
}
};
</script>
pict :
i try to use :
<button #click="toggle = ! toggle">
<i v-if="!toggle" class="fas fa-bars"></i>
<i v-if="toggle" class="fas fa-times"></i>
</button>
it still resulting the same result
You need to add a key to the icons.
<button #click="toggle = ! toggle">
<i v-if="!toggle" key="bars" class="fas fa-bars"></i>
<i v-if="toggle" key="times" class="fas fa-times"></i>
</button>
The key will tell Vue's algorithm that the icons are in fact different elements. Without that the virtual dom representation thinks that they are the same element.
Try switching the classes using condition
<button #click="toggle = ! toggle">
<i class="fas" :class="toggle?'fa-times':'fa-bars'"></i>
</button>

Why click event works after two clicks VANILLA

I am trying to trigger a function through a event listener with only one click.
But it occurs after two click (in the first time) if I don't do F5 its trigger after one click.
Code:
HTML
<div class="main-header-navbar">
....
<span class="main-header-navbar-right-icons">
<i class="fas fa-search header-icon"></i>
<i class="fas fa-plus header-icon"></i>
</span>
</div>
JS
const ADD_FORM_BUTTON = document.querySelector(".fa-plus");
ADD_FORM_BUTTON.addEventListener("click", function (event) {
event.preventDefault();
if (ADD_FORM.style.display === "none") {
ADD_FORM.style.display = "flex";
} else ADD_FORM.style.display = "none";
});
What am I missing?
You probably need to add style="display: none;" to your ADD_FORM so that it's initially hidden, then when you click on the fa-plus it will display it. See the snippet below:
const ADD_FORM_BUTTON = document.querySelector(".fa-plus");
const ADD_FORM = document.getElementById("form");
ADD_FORM_BUTTON.addEventListener("click", function(event) {
event.preventDefault();
if (ADD_FORM.style.display === "none") {
ADD_FORM.style.display = "flex";
} else {
ADD_FORM.style.display = "none"
};
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.13.0/css/all.min.css" rel="stylesheet" />
<div class="main-header-navbar">
<span class="main-header-navbar-right-icons">
<i class="fas fa-search header-icon"></i>
<i class="fas fa-plus header-icon"></i>
</span>
<div id="form" style="display: none;">ADD_FORM</div>
</div>

toggle button on click in jquery

First, let me clear you all one thing that i have already searched a lot but couldn't find the answer which will solve my problem. I have a button which when i click it's icon changes and some functions called than when i again click on that button it's icon must be revert and same functions called again.
I have this button:
<button type="button" class="btn" id="voice_icon" title="microphone">
<i style="font-size: 24px;" class="fa fa-microphone fa-2x voice_control" id="voice_control"></i>
<small class="toolbar-label mic-btn" id="mic">Mic.</small>
</button>
while clicking on that button these functions and classes should be called:
$('#voice_icon').click(function () {
voiceAtion.voice();
test.start();
$('#voice_control').addClass("fa-microphone-slash").removeClass("fa-microphone");
$('#mic').html("<i class='fa fa-spinner fa-pulse fa-1x fa-fw'></i>");
});
And when i again click on that icon these icons and classes should be called again :
test.abort();
$('#voice_control').addClass("fa-microphone").removeClass("fa-microphone-slash");
$('#mic').html("Mic.");
$('#voice_icon').click(function() {
voiceAtion.voice();
test.start();
$('#voice_control').addClass("fa-microphone-slash").removeClass("fa-microphone");
$('#mic').html("<i class='fa fa-spinner fa-pulse fa-1x fa-fw'></i>");
});
test.abort();
$('#voice_control').addClass("fa-microphone").removeClass("fa-microphone-slash");
$('#mic').html("Mic.");
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button type="button" class="btn" id="voice_icon" title="microphone">
<i style="font-size: 24px;" class="fa fa-microphone fa-2x voice_control" id="voice_control"></i>
<small class="toolbar-label mic-btn" id="mic">Mic.</small>
</button>
Try something like this first time click goes to else and for second click it goes to if. so on..
$('#voice_icon').click(function() {
var clicks = $(this).data('clicks');
if (clicks) {
//first code
} else {
//second code
}
$(this).data("clicks", !clicks);
});
Instead of addClass/removeClass use toggleClass.
$('#voice_control').toggleClass("fa-microphone-slash fa-microphone");
use hasClass for check which class to remove and add
$(document).ready(function() {
$('#voice_icon').click(function() {
if ($('#voice_control').hasClass("fa-microphone")) {
$('#voice_control').addClass("fa-microphone-slash").removeClass("fa-microphone");
$('#mic').html("<i class='fa fa-spinner fa-pulse fa-1x fa-fw'></i>");
} else {
$('#voice_control').addClass("fa-microphone").removeClass("fa-microphone-slash");
$('#mic').html("Mic.");
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button type="button" class="btn" id="voice_icon" title="microphone">
<i style="font-size: 24px;" class="fa fa-microphone fa-2x voice_control" id="voice_control"></i>
<small class="toolbar-label mic-btn" id="mic">Mic.</small>
</button>
// You can also use global variable and check for true false:
<button type="button" class="btn" id="voice_icon" title="microphone">
<i style="font-size: 24px;" class="fa fa-microphone fa-2x voice_control" id="voice_control"></i>
<small class="toolbar-label mic-btn" id="mic">Mic.</small>
</button>
<script>
var x = true;
$('#voice_icon').click(function () {
if(x){
$('#voice_control').removeClass("fa-microphone").addClass("fa-microphone-slash")
x = false;
}
else{
$('#voice_control').addClass("fa-microphone").removeClass("fa-microphone-slash")
x = true;
}
$('#mic').html("<i class='fa fa-spinner fa-pulse fa-1x fa-fw'></i>");
});
</script>

jQuery cut out content between 2 tags

Thanks to Turnip below I was able to grab a chunk of HTML.
I would like to add the sections of this chunk to an object like so:
[{"quote":"xxx","author":"yyy"},{"quote":"xxx","author":"yyy"}]
The quote is in the tags:
...
$(document).ready(function() {
var origPage = "";
$.get("https://crossorigin.me/http://www.brainyquote.com/quotes/keywords/websites.html", {}, function(content){
origPage = content;
}, "html");
$("#myLink").on('click', function() {
var kill = origPage;
var oPage = $(kill);
var me = $('.bqQt', oPage);
$("div").html(me);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div></div>
<a class ="clicker" id= "myLink" href="#" >click me</a>
And the autor is between the tags:
...
Right now the html structure for the items is as follows:
<div class="masonryitem boxy bqQt bqShare">
<div class="boxyPaddingBig">
<span class="bqQuoteLink">I'm on a strict gossip diet. No gossip websites, no gossip magazines. Otherwise, I find it paralyzing to exist.
</span><br>
<div class="bq-aut">Julie Bowen</div>
</div>
<div class="bq_q_nav boxyBottom boxyPaddingSmall" style="overflow:hidden;">
<div class="body bq_boxyRelatedLeft bqBlackLink">
Diet,
Gossip,
Magazines
</div>
</div>
<div class="bq_q_nav bq_q_btns boxyPaddingSmall" style="overflow:hidden;">
<div class="bq20">
<div ng-show="showMemberButtons()" class="bqAddQuote bqAddQuoteLg" style="float:right">
<span data-ng-click="onFavoriteClicked(455734)" data-ng-class="favCssClass(455734)" class="fa favHeart pointerCursor" onclick="hCl('/quotes/keywords/websites','/quotes/quotes/j/juliebowen455734','1')"></span><span data-ng-click="onAddToCollectionClicked(455734)" data-ng-class="collectionCssClass(455734)" class="fa favAddToCol pointerCursor" onclick="pCl('/quotes/keywords/websites','/quotes/quotes/j/juliebowen455734','1')"></span>
</div>
<table class="bq_tbl_nospc">
<tbody><tr>
<td valign="top">
<div class="nonJsIcons">
<a href="/share/fb/455734?sr=ql&from=%2Fquotes%2Fkeywords%2Fwebsites.html" class="fa-stack fa-lg fbShare" rel="nofollow" target="_blank">
<i class="fa fa-circle fa-stack-2x"></i>
<i class="fa fa-facebook fa-stack-1x fa-inverse"></i>
</a>
<a href="/share/tw/455734?sr=ql&from=%2Fquotes%2Fkeywords%2Fwebsites.html&ti=Websites+Quotes" class="fa-stack fa-lg twShare" rel="nofollow" target="_blank">
<i class="fa fa-circle fa-stack-2x"></i>
<i class="fa fa-twitter fa-stack-1x fa-inverse"></i>
</a>
</div>
</td>
</tr>
</tbody></table>
</div>
</div>
</div>
I am getting the html using:
<script>
$(document).ready(function() {
var origPage = "";
$.get("https://crossorigin.me/http://www.brainyquote.com/quotes/keywords/websites.html", {}, function(content){
origPage = content;
}, "html");
$("#myLink").on('click', function() {
var kill = origPage;
var oPage = $(kill);
var me = $('.bqQt', oPage);
$("div").html(me);
});
});
</script>
You already had the dom elements, you just needed to loop them and get the author and quote. Hope this helps.
$(document).ready(function() {
var apiCall = (function(){
return $.ajax({
method: "GET",
url: "https://crossorigin.me/http://www.brainyquote.com/quotes/keywords/websites.html",
cache: true
});
})();
var getAuthQuotes = function(elems){
var quoteArray = [];
$.each(elems, function(index, elem){
var obj = {};
var $elem = $(elem);
obj.quote = $elem.find('span.bqQuoteLink').text();
obj.author = $elem.find('div.bq-aut').text();
quoteArray.push(obj);
});
return quoteArray;
}
$("#myLink").on('click', function(e) {
e.preventDefault();
apiCall.then(function(origPage){
var kill = origPage;
var oPage = $(kill);
var me = $('.bqQt', oPage);
var authQuoteObj = getAuthQuotes(me);
//here is the array of objects
console.log(authQuoteObj);
});
});
});

Changing CSS based on service variables

I'm new to Angular, but it seems to be the "Angular way" to avoid DOM manipulation whenever possible. I am not sure if I'm taking the right approach.
I have three buttons on the bottom (next,back, and home). These get enabled and disabled by way of the actions of other controllers. For example if a text box is NULL the next button will be disabled until something is entered. I have the following:
<div ng-controller="nextBackController" class="navbar navbar-app navbar-absolute-bottom">
<div class="btn-group justified">
<i class="fa fa-arrow-left fa-navbar" ng-class="{'btn-disabled' : btnBack}"></i> Back
<a id="btnHome" ng-click="handleClick()" href="#/" class="btn btn-navbar btn-icon-only btn-bounded" ng-class="{'btn-disabled' : btnHome}"><i class="fa fa-home fa-navbar"></i> Home</a>
Next <i class="fa fa-arrow-right fa-navbar" ng-class="{'btn-disabled' : btnNext}"></i>
</div>
</div>
And now for the JS:
app.service("nxtBackClick", function($rootScope, bottomButtonWatcher) {
this.btn = "";
this.broadcast = function(btn) {
//Toggle the Next button as an example
bottomButtonWatcher.btnNext = ~bottomButtonWatcher.btnNext;
//set the btn that is clicked
this.btn = btn;
$rootScope.$broadcast('bottomBtnClick');
};
});
app.service("bottomButtonWatcher", function($rootScope) {
//Set all these to disabled
this.btnHome = true;
this.btnNext = false;
this.btnBack = true;
});
And now the controller:
//####################### - Next Back Controller ########################
app.controller("nextBackController",
function($scope, nxtBackClick, bottomButtonWatcher){
$scope.btnHome = bottomButtonWatcher.btnHome;
$scope.btnNext = bottomButtonWatcher.btnNext;
$scope.btnBack = bottomButtonWatcher.btnBack;
$scope.handleClick = function(btn) {
nxtBackClick.broadcast(btn);
};
}
);
Having both a class attribute and an ng-class attribute can be problematic. They should both be condensed into a single ng-class attribute. You are already passing an object, so just add another property to it. Setting classes to always be shown is accomplished by setting their property to true.
<div ng-controller="nextBackController" class="navbar navbar-app navbar-absolute-bottom">
<div class="btn-group justified">
<a href="#/" class="btn btn-navbar btn-icon-only btn-bounded">
<i ng-class="{'fa fa-arrow-left fa-navbar': true, 'btn-disabled' : btnBack}"></i>
Back
</a>
<a id="btnHome" ng-click="handleClick()" href="#/" ng-class="{'btn btn-navbar btn-icon-only btn-bounded':true, 'btn-disabled' : btnHome}">
<i class="fa fa-home fa-navbar"></i>
Home
</a>
<a href="#/second" class="btn btn-navbar btn-icon-only">
Next
<i class="" ng-class="{'fa fa-arrow-right fa-navbar':true, 'btn-disabled' : btnNext}"></i>
</a>
</div>
</div>
You're using $rootScope.$broadcast but nobody is listening, you need to have a scope watcher in your controller that actually controls the buttons:
//####################### - Next Back Controller ########################
app.controller("nextBackController",
function($scope, nxtBackClick, bottomButtonWatcher){
$scope.btnHome = bottomButtonWatcher.btnHome;
$scope.btnNext = bottomButtonWatcher.btnNext;
$scope.btnBack = bottomButtonWatcher.btnBack;
$scope.handleClick = function(btn) {
nxtBackClick.broadcast(btn);
};
$scope.$watch('bottomBtnClick', function(buttonVal){
$scope[buttonVal] = true;
});
}
);

Categories