I can´t remove the last item of array - javascript

I can remove any item of array unless the last one. I also use angularjs to show information in the view. I don´t know what is happening with the last item of this array. Please, anyone can help me?
Here is HTML:
<div class="row">
<div class="col-md-12">
<h4><strong>Documento {{index + 1}} de {{documentos.length}}:</strong> {{documentos[index].nome}}</h4>
<iframe style="background: #ccc;" ng-show="exibirPreview" frameborder="0" ng-src="{{versaoLink}}" width="100%" height="300px"></iframe>
<div class="alert alert-warning" ng-hide="exibirPreview">
#Html.Raw(Resources.Dialog.SignDocuments.TypeDocumentCanNotPreDisplayed)
</div>
<hr />
<div class="pull-right btn-row" ng-show="documentos.length > 1">
<button class="btn btn-default" type="button" ng-click="RemoveDoc(index)"><i class="fa fa-fw fa-times"></i> #Resources.Common.RemoveDocList</button>
</div>
</div>
</div>
Here is js/angularjs
$scope.documentos = [
{nome:"document1", chave: "8F65579E3737706F", extensao:".pdf"},
{nome:"document2", chave: "8F65579E3730007F", extensao:".pdf"},
{nome:"document3", chave: "8545579E3737706F", extensao:".pdf"},
{nome:"document4", chave: "8555579E3730007F", extensao:".pdf"}
]
$scope.ViewLink = function () {
var versao = $scope.documentos[$scope.index];
$scope.exibirPreview = versao.extensao == ".pdf" || versao.extensao == ".txt";
if (!$scope.exibirPreview) {
$scope.versaoLink = '';
} else {
$scope.versaoLink = '/Documento/VersaoView?chave=' + versao.chave;
}
};
$scope.ViewLink();
$scope.RemoveDoc = function (index) {
$scope.documentos.splice(index, 1);
$scope.ViewLink();
};
Or Plunker

In your HTML you are preventing the deletion of the last element:
<div class="pull-right btn-row" ng-show="documentos.length > 1">
<!-- -->
</div>
documentos.length > 1 means "hide when it reaches one item in the array".
It should be documentos.length == 0.
It's either this or your index value starts from 1 and not from 0.

The simplest solution would be to change your remove function to take in the document instead of the index. Try this:
$scope.RemoveDoc = function(document) {
var index = $scope.documents.indexOf(document);
$scope.documents.splice(index, 1);
}
in view:
<button class="btn" type="button" ng-click="RemoveDoc(document)">Delete</button>

Related

How to make a loop check off only one item at a time using vanilla javascript?

I am building a simple todo list, but I am having a bit of trouble for about 2 weeks now trying to solve this problem I have with the loops. Can someone explain what I am doing wrong please? I want to check each item off one at a time, I'm currently using for loops to iterate thru each item. The problem I have been facing is that the loops cause all items to be checked off at the same time. I have tried simple if else statements, switches, while loops, nested for loops. Any advice would be greatly appreciated. Code below.
Javascript
const check = document.querySelectorAll('.check');
const uncheck = document.querySelectorAll('.uncheck');
const li = document.querySelectorAll('li');
function checkItem(event) {
for(let i = 0; i < li.length && i < check.length && i < uncheck.length; i++) {
switch(event.target.classList.contains('far')) {
case true:
li[i].style.textDecoration = 'line-through'
check[i].style.display = 'block';
uncheck[i].classList.toggle('check');
break;
default:
li[i].style.textDecoration = 'none';
check[i].style.display = 'none';
uncheck[i].classList.toggle('uncheck');
}
}
}
EJS
<body onclick="checkItem(event)">
<div id="wrapper">
<div id="interface">
<header>
<i class="fas fa-sync-alt" id="delAllBtn"></i>
<div id="datebox">
<p id="time">4:20pm</p>
<br>
<p id="date">September 24, 2020</p>
</div>
</header>
<div id="userInput">
<form action="/list" method="POST">
<input type="text" placeholder="Enter item.." name="item" autofocus required>
<button type="submit" id="addBtn"><i class="fas fa-plus-circle"></i></button>
</form>
</div>
<main>
<ul id="list">
<% for(let i = 0; i < list.length; i++) {%>
<li class="list-item">
<div class="checkbox">
<i class="far fa-circle uncheck"></i>
<i class="fas fa-check-circle check"></i>
</div>
<span><%= list[i].item %></span>
<div id="buttons">
<button type="submit" data-update="<%= list[i]._id %>" class="saveBtn"><i class="fas fa-edit"></i></button>
<button type="button" data-update="<%= list[i]._id %>" class="editBtn"><i class="fas fa-edit"></i></button>
<button type="button" data-delete="<%= list[i]._id %>" class="delItemBtn"><i class="fas fa-trash-alt"></i></button>
</div>
</li>
<% } %>
</ul>
</main>
<footer>
<p>Footer</p>
</footer>
</div>
</div>
<script src="javascripts/main.js"></script>
</body>
It seems like you have answered your own question here, all items are being checked off because you are using a for loop. Try using e.target after defining a function that you want to call after a click event. This way you will only change the individual item that you click on:
function checkItem(el) {
if (el.classList.contains('uncheck')) {
el.classList.add("check");
el.classList.remove("uncheck");
}
}
document.querySelector('#list').addEventListener('click', (e) => {
checkItem(e.target);
});
You are evaluating event.target on every iteration of the for loop.
You should do it based on the current element of the iteration so that each element gets updated based on its own properties.

Removing selected row from an array using splice in angularjs

I have an issue in removing the particular item from an array.I have tried using splice but, the last row is removing instead of the particular row.I am providing the plunker link here :
$scope.rows.splice($index, 1);
https://plnkr.co/edit/WETSLqOXlTwiHq4p9IUt?p=preview
Any help would be appreciated . Thanks
just try the following
http://jsfiddle.net/oymo9g2f/2/
you have some problem with your array splice
Not quite sure what you're trying to accomplish (as your code looks like you are quite new to AngularJS, but I created a different (but similar) implementation that should fit your needs (it's easier to read IMHO and is scalable):
HTML:
<div class="card ">
<form name="add_destination_form" class="col s12" ng-submit="add_destination_form.$valid && addDestination_Details(destination_details)" novalidate>
<div class="row" ng-repeat="row in rows track by $index">
<div class="col s12 m4" >
<label for="destination_features1" >Features</label>
<textarea id="destination_features1" name="destination_features1_{{$index}}" ng-model="destination_details.destination_features1[$index]" placeholder="Data Here" type="text" ></textarea>
</div>
<button ng-show="show_removebtn" id="removeButton" ng-click="removeDynamically($index)" type="button">Remove</button>
</div>
<div class="col s12 m4">
<button class="waves-effect waves-light btn" ng-click="addDynamically()" type="button">Add More</button>
</div>
<div class="row">
<div class="col s12 m4">
<button type="submit">Submit</button>
</div>
</div>
</form>
</div>
JavaScript:
$scope.rows = [{
"row_num": 0,
"text": ""
}];
$scope.addDynamically = function (index) {
console.log(index);
$scope.rows.push({
"row_num": index,
"text": ""
});
};
$scope.removeDynamically = function (index) {
$scope.rows.splice(index, 1);
};
Plunker
just use this code. For text area used ng-model="row.value" and related change in controller
in html: just shown ng-repeat part
<div class="row" ng-repeat="row in rows track by $index">
<div class="col s12 m4" >
<label for="destination_features1" >Features</label>
<textarea id="destination_features1" name="destination_features1_{{$index}}" ng-model="row.value" placeholder="Data Here" type="text" ></textarea>
</div>
<button ng-show="show_removebtn" id="removeButton" ng-click="removeDynamically($index)" type="button">Remove</button>
</div>
and in controller:
$scope.rows = [];
$scope.current_rows = 0;
$scope.destination_details = {};
$scope.rows.push({
row_num: $scope.current_rows,
value: ''
});
$scope.addDynamically = function() {
$scope.current_rows += 1;
$scope.rows.push({
row_num: $scope.current_rows,
value: ''
});
if ($scope.rows.length > 1) {
$scope.show_removebtn = true;
}
};
$scope.removeDynamically = function(index) {
if (index > -1) {
$scope.rows.splice(index, 1);
}
};
You need to add line:
$scope.destination_details = {"destination_features1": ['1']};
at the beginning.
Also need to remove model properly when removing element:
$scope.destination_details.destination_features1.splice($index, 1);
https://plnkr.co/edit/pe44Moqe7ymegYFTrXJu?p=preview

Load More Button JS - Load new content on page

I'm trying to develop a Load-More button using Javascript calling an API done with PHP.
So far, so good. I can load the new objects in a range i += i + 4 (I load three new comments everytime I press the button).
This is my load-more button:
$(document).ready(function () {
$(".load-more").on('click', function () {
var tab = $(this).data('tab');
var next_page = $(this).data('next-page');
console.log(next_page);
console.log(tab);
$.get($(this).data('url') + '?tab=' + tab + '&page=' + next_page, function (data) {
addNewQuestions($.parseJSON(data));
});
});
});
And for every object loaded I want to print each of these html blocks.
<div class="question-summary narrow">
<div class="col-md-12">
<div class="votes">
<div class="mini-counts"><span title="7 votes">
{if $question['votes_count']}
{$question['votes_count']}
{else}
0
{/if}
</span></div>
<div>votes</div>
</div>
<div {if $question['solved_date']}
class="status answered-accepted"
{else}
class="status answer-selected"
{/if}
title="one of the answers was accepted as the correct answer">
<div class="mini-counts"><span title="1 answer">{$question['answers_count']}</span></div>
<div>answer</div>
</div>
<div class="views">
<div class="mini-counts"><span title="140 views">{$question['views_counter']}</span></div>
<div>views</div>
</div>
<div class="summary">
<h3>
<a href="{questionUrl($question['publicationid'])}" class="question-title" style="font-size: 15px; line-height: 1.4; margin-bottom: .5em;">
{$question['title']}
</a>
</h3>
</div>
<div class = "statistics col-sm-12 text-right" style="padding-top: 8px">
<span>
<i class = "glyphicon glyphicon-time"></i>
<span class="question-updated-at">{$question['creation_date']}</span>
</span>
<span>
<i class = "glyphicon glyphicon-comment"></i>
<span class="question-answers">{$question['answers_count']}</span>
</span>
</div>
</div>
</div>
The problem is that I have several conditions, as {if$question['votes_count']} and I'm struggling because I don't know how get those variables when rendering the html.
Then I found something but I can't figure out how to adapt to my case
On that addNewQuestions I think that a good approach would be:
function addNewQuestions(objects) {
$.each(objects, function (i, object) {
console.log(object);
var lastItem = $('div.active[role="tabpanel"] .question-line:last');
var newLine = lastItem.clone(true);
var newObject = newLine.find('.question-col:eq(' + i + ')');
newObject.find('.question-info-container').attr('data-id', object.publicationid);
newObject.find('.vote-count').html(object.votes);
updateTitleAndLink(newObject.find('.question-title'), object);
lastItem.after(newLine);
});
}
function updateTitleAndLink(questionTitle, object) {
questionTitle.attr('href', questionTitle.data('base-question-url') + object.publicationid);
questionTitle.html(object.title);
}
But nothing happens and I can't figure out why.
Any idea or suggestion?
Kind regards

Bind paired data in object to another element outside ng-repeat - angular

I have this array of objects that I need to work with:
$scope.pdfs = [
{ "pdf_title": "Corporate Hire", "attached_file": "http://file1.jpg"},
{ "pdf_title": "Wedding Hire", "attached_file": "http://file2.jpg"},
{ "pdf_title": "Filming Hire", "attached_file": "http://file3.jpg"}
];
The pdf_file value is ng-repeated in li's.
What I want to do is if that li is clicked, to push its paired to another div, say the src for an href.
Here are my workings, but not quite correct:
Controller function:
$scope.bindWithFile = function(value) {
var currentValue = $scope.corpResult = value;
// pdfs support
var pdfs = $scope.pdfs;
for (var i = pdfs.length - 1; i >= 0; i--) {
if (currentValue == hasOwnProperty(key[pdfs])) {
value[pdfs] = $scope.corpLinkHref;
}
};
Markup:
<div class="w-12" ng-controller="corpHireController">
<div class="c-6-set">
<ul>
<li ng-repeat="pdf in pdfs" class="col-7 link link-inherit" ng-click="bindWithFile(pdf.pdf_title)">{{::pdf.pdf_title}}</li>
</ul>
</div>
<div class="c-6-set">
<div class="w-12">
<i class="fs-4 col-7 icon icon-pdf"></i>
</div>
<span class="col-7 h4" ng-bind="corpResult"></span>
<button ng-href="{{::corpLinkHref}}" class="button green2-button smaller-letters full-width">Download</button>
</div>
</div>
What is needed:
Clicking on the titles on the left, binds the pdf_title under the pdf icon and binds the attached_file to the button's href
Instead of passing the title of the selected pdf, why not passing the whole object. This way you don't have to performance any find or search function.
Markup:
<div class="w-12" ng-controller="corpHireController">
<div class="c-6-set">
<ul>
<li ng-repeat="pdf in pdfs" class="col-7 link link-inherit"
ng-click="bindWithFile(pdf)">
{{::pdf.pdf_title}}
</li>
</ul>
</div>
<div class="c-6-set">
<div class="w-12">
<i class="fs-4 col-7 icon icon-pdf"></i>
</div>
<span class="col-7 h4" ng-bind="corpResult"></span>
<button ng-href="{{::corpLinkHref}}"
class="button green2-button smaller-letters full-width">
Download
</button>
</div>
</div>
Controller
$scope.bindWithFile = function(selectedPdf) {
$scope.corpResult = selectedPdf.pdf_title;
$scope.corpLinkHref = selectedPdf.attached_file;
}

Is JQuery breaking my functionality?

I am making an app, the user can either select an item or use their camera to get the qr code which translates into an item's ID.
The problem is that I think some JQuery is messing with my scope from working properly.
I have to get the QR code by listening to an innerHtml change, once it changes (DOMSubtreeModified) the following occurs.
var index = 0;
$('#result').one('DOMSubtreeModified', function(e) {
var code = "";
if (e.target.innerHTML.length > 0) {
code = e.target.innerHTML;
$scope.ToRun(code);
}
});
$scope.ToRun = function(code) {
for (i = 0; i < $scope.plantList.length; i++) {
if ($scope.plantList[i].plantcode == code) {
index = i;
break;
}
}
$scope.currentPlant = $scope.plantList[index];
$scope.plantDetails = false;
$scope.searchDetails = true;
}
For some reason the following does not have any effect on my ng-classes. As when an item is selected I hide the input dialogs, and show the result one.
$scope.plantDetails = false;
$scope.searchDetails = true;
But when a user selects the item manually it works just perfectly. (the items have an ng-click on it)
$scope.viewPlant = function(plant) {
$scope.currentPlant = plant
$scope.plantDetails = false;
$scope.searchDetails = true;
};
And the above works fine, with the ng-click. So why won't my new function that listens for an innerHtml change work?
HTML snippet
<div ng-class="{ 'hidden': searchDetails }">
<!-- CHOOSE INPUT TYPE -->
<div class="form-group" style="margin-bottom:0px">
<div class="btn-group btn-group-justified">
<div class="btn-group">
<button type="button" class="btn btn-default" ng-click="digits = false; qr = true">Plant Code</button>
</div>
<div class="btn-group">
<button type="button" class="btn btn-default" ng-click="digits = true; qr = false">QR Code</button>
</div>
</div>
</div>
<br />
<!-- QR CODE INPUT -->
<div ng-class="{ 'hidden': qr }">
<img id="blah" src="./images/placeholder.png" />
<span class="btn btn-default btn-file">
<i class="glyphicon glyphicon-camera"></i>
<input type="file" onchange="readURL(this);handleFiles(this.files)">
</span>
<div id="result">xxxxxx</div>
<canvas id="qr-canvas" width="800" height="600"></canvas>
</div>
<!-- MANUAL SELECTION INPUT -->
<div ng-class="{ 'hidden': digits }">
<input ng-model="search.$" style="width:100%; font-size:30px; text-align:center" placeholder="Plant Code" />
<div style="overflow: auto; max-height:250px">
<table class="table table-striped" style="background-color:lightblue">
<tr ng-repeat="plant in plantList | filter:search" ng-click="viewPlant(plant)" style="cursor:pointer">
<th>{{plant.name}}</th>
<th>{{plant.plantcode}}</th>
</tr>
</table>
</div>
</div>
<div>
</div>
</div>
<div ng-class="{ 'hidden': plantDetails }">
// results - this should appear when one of the above is entered.
// works for manual selection, but not qr code
</div>
Just confused on why my QR input will not fire off the change-class options to hide the searchDetails div and show the plantDetails div
EDIT: Doing a small test, it seems that my class variables are indeed not updating at all. I just put the values at the bottom of my page and they do not update when hitting the block of:
$scope.plantDetails = false;
$scope.searchDetails = true;
You need to let Angular know about the change. Add this at the end of your method and let me know if it works.
$scope.$apply();

Categories

Resources