How to show multiple attachments in JavaScript - javascript

I'm completly new in JavaScript and HTML, and i want to attach some files in my site. The problem is that: when i want to attach some files, from the view, i selected them but in the view appear only one file instead of the list of file that i selected.
For example, if I attach file1, file2 and file3, it shows me only file1, like that:
So I want to obtain this situation:
Here is the code:
JS wrote by me to fix the problem, but it shows me the same result (only one file appears):
const fileinput = require("./button");
const updateList = () => {
var arrayFiles = document.getElementById("input_issue").files;
for (i = 0; i < arrayFiles.length; i++) {
fileinput.append('<i class="text">arrayFiles[i].name</i>')
}
}
<form id="issueModalFormAttachment" method="POST">
<table>
<tr class="form-group">
<td class="label">{% translate 'Attachments' %}</td>
<td class="field">
<input id="input_issue" name="input_issue[]" type="file" class="file" multiple data-show-upload="true" data-show-caption="true">
</td>
</tr>
</table>
</form>
I don't know if it is useful because i know nothing about html and js and someone else wrote the entire HTML and JS code... but my tutor gave me the issue to fix this problem
ArrayFiles should be the array of files that i want to upload. I thought that with a for loop i could scan the array and append the files in the button.
Can someone help me? Sorry again for the ignorance
Edit: I solved in this way
const setupInput = () => {
$('#input_issue').change( () => {
let arrayFiles = document.getElementById("input_issue").files;
for(i=1;i<arrayFiles.length;i++){
let t = $('#button_file_upload_issue i.text').text();
$('#button_file_upload_issue i.text').text(t + ', '+ arrayFiles[i].name);
}
})
}

try something like this:
fileinput.innerHTML += '<i class="text">arrayFiles[i].name</i>';

Related

Event firing multiple times in Vuejs

So, I wrote a function that using which the user can upload multiple files.
<input multiple type="file" id="inputFile" ref="fileSelect" #click="uploadfiles"/>
uploadfiles(){
'use strict'
const inputFile = document.getElementById('inputFile')
console.log(inputFile)
inputFile!.addEventListener('change',async e => {
const files = (e.target as HTMLInputElement).files
const reader = new FileReader()
console.log(files)
console.log(reader)
// New set of results each time.
this.results.splice(0)
for (const file of files!){
if(file["type"] == "application/json"){
this.results.push(await this.readjsonfile(reader, file))}
else if(file["type"]=="text/csv"){
this.results.push(await this.readcsvfile(reader, file))
}
}
})}
Now when I upload a file for the 1st time it works fine, but when I click on the choose files button again to upload another file, it uploads that file twice.
I think the problem is that when I click again on choose files I "activate" the uploadfiles function again, which causes the Event Listener to fire twice, but I am not sure how to do it any other way.
I am new to JavaScript and vuejs, so any suggestions are greatly appreciated.
Thanks to #Daniel I finally ended up figuring out how to fix this.
My final code is
<input multiple type="file" id="inputFile" ref="fileSelect" #change="uploadfiles"/>
uploadfiles(event){
'use strict'
console.log(event)
//console.log(event.target.files)
const q = [event.target.files]
q.forEach(async w => {
const reader = new FileReader()
this.results=[]
for(const file of w){
if(file["type"] == "application/json"){
this.results.push(await this.readjsonfile(reader, file))}
else if(file["type"]=="text/csv"){
this.results.push(await this.readcsvfile(reader, file))
}
}
})
console.log(this.results)
}
The reason is that you're adding inputFile!.addEventListener every time the user clicks on the input form
Instead, if you were to use #change, instead of #click, that should not be happening any more.
example:
<script setup>
import {ref} from "vue"
let files = ref([])
function uploadfiles(event){
files.value.splice(0);
[...event.target.files].forEach(async file => {
// do the logic here
files.value.push(file)
})
}
</script>
<template>
<input multiple type="file" id="inputFile" ref="fileSelect" #change="uploadfiles"/>
<pre>{{files}}</pre>
</template>
SFC playground

Reload Data with .sort from Dynamic Table with Jquery | JSON | Sort with New Data

I have been trying for a few days that when I use the .sort property the data is eliminated or modified instead of it being reloaded as new lines.
Attach Captures from the code Working
Image1 How work the code when i press the button, this sort to the highest price to lowest but how do you can see in the second image, the code appears up and this not delete the old data
Marked with "X" the data that does not have to show
this fragment is the one that generates the tables dynamically
const mostrarProductos = () => {
$.getJSON(URLJSON, (respuesta) => {
for (let z of respuesta) {
productosv2.push(z);
}
for (let x of productosv2) {
$("#fila").append(`
<tr class="deleteProductos">
<div class="card text-center" style="width: 18rem;" id='btnBorrarCarrito'>
<div class="card-body">
<input type="hidden" id="idProd" value="${x.id}"> </td>
<td class="card-title" id="${x.id}">${x.producto}</h2> </td>
<td class="card-text">$ ${x.precio}</p></td>
<div class="btn-group" role="group" aria-label="Basic mixed styles example">
<td><button type="button" class="btn btn-success" onclick="agregarCarrito(${x.id})">Agregar</button></td>
</div>
</div>
</div>
</tr>
`);
}
$("#fila").fadeIn("5000");
});
};
And this function is what orders them
function respuestaClickExpensive() {
$("#fila").html('');
let productosordenados = productosv2.sort((a, b) => {
if (a.precio > b.precio) {
return -1;
}
if (a.precio < b.precio) {
return 1;
}
return 0;
});
return productosordenados;
}
The one that orders them from smallest to largest is the same only that different signs and names.
As you can see I tried to use a ".html ("")" since previously in another cart attempt it used .innerHtml (Which does not work in this case either, Also the code of the cart is totally different from that moment that it worked for me
)
I tried the following:
$ ("#fila"). empty ();
Make another function to clean with .empty
Use Native JavaScript to generate the code.
$ ("#fila"). remove (); this removes all the content for me but does not regenerate it.
Change the HTML tag "Row" to a previous div which, since the div was not generated again, did not generate it again.
$ ("#fila tr"). remove ();
And some more things that I don't remember right now.
If you can guide me on what I did wrong or any suggestions to fix it, I appreciate it.
If I had to follow a template about posting on StackOverFlow or having chosen or named in a different way, I appreciate your comment since it is my first post
Project notes of possible relevance: The complete code outside of html and css is made with Native JavaScript, Jquery, Ajax, SASS and BootStrap.

How to Check/Unchecked the check box list by retrieving the data from database in ASP.NET MVC

i am very new to ASP.NET MVC and trying to make a project tracking tool.
i want to show a list of Questions from a table when page loads and it works.
but when a user click on the "Select Category Name" he should get all Questions as above and a check mark on the Questions which are related to specific category.as of now i am filtering and getting only the filtered Questions which is correct but the list should show all other categories questions as unchecked.
i have a table for Questions, Category and a one to many relationship between both of them hence i made a mapping table named QuestionCategoryMapping Table.
the problem i am facing that i don't know how to filter first all the questions and then later put a checkbox when a user select from list.
i have made two separate functions both are working but i need the separated functionality together.
here are my code spinets.
// test code for partial view in project
QuestionDataAccessLayer questionDataAccessLayer = new QuestionDataAccessLayer();
//controller to add a partial view in create and edit question page
public new PartialViewResult PartialView()
{
IEnumerable<Questions> questions = questionDataAccessLayer.GetAllQuestion();
return PartialView("Partial_View", questions);
}
QuestionCategoryDataAccessLayer questionCategoryDataAccess = new QuestionCategoryDataAccessLayer();
public new PartialViewResult PartialView1(int id)
{
IEnumerable<QuestionCategory> questionCategory = questionCategoryDataAccess.GetQuestionsPerCategory(id);
return PartialView("Partial_View1", questionCategory);
}
the JavaScript,HTML files are as below:
<script>
// code to update the partial view
window.onload = function () {
$.ajax({
url: 'PartialView',
data: {},
type: 'Get',
success: function (response) {
$("#Questionpartial").html(response)
}
});
}
//code to update the questions according to the selected chapter
$("body").on("change", "#Qpartial", function () {
var CatgId = $("#Qpartial").val();
$.ajax({
url: 'PartialView1',
data: { id: CatgId },
type: 'Get',
success: function (response) {
$("#Questionpartial").html(response)
console.log(CatgId);
}
})
});
</script>
#model IEnumerable<EPQProjectTrackingTool.Models.QuestionCategory>
<table #*border="1" class="table table-striped"*#>
<thead>
<tr>
<th>
#Html.DisplayNameFor(model => model.Question)
</th>
</tr>
</thead>
<tbody>
#foreach (var item in Model)
{
<tr>
<td>
#*#Html.DisplayFor(modelItem => item.Question)*#
<input name="AreChecked" type="checkbox" checked="checked" value="#item.Question" /> #item.Question<br />
</td>
</tr>
}
</tbody>
</table>
there is one more file which is same HTML but only showing the full list as show in the above pic.
and the stored procedure in sql is:
CREATE procedure [dbo].[spGetAllMapping_Question_Category]
as
Begin
SELECT
mpq.UID,mpq.Question_ID_FK_1,eq.Question ,mpq. Cat_ID_FK_2, ec.Description, mpq.Valid_From,
mpq.Valid_To,c.Chapter_Name
FROM
EPQ2.Category ec,EPQ2.Questions eq, EPQ2.Mapping_Question_Category mpq, EPQ2.Chapter c
WHERE
mpq.Question_ID_FK_1 = eq.Question_ID_PK
and mpq.Cat_ID_FK_2 = ec.Cat_ID_PK
and c.Chapter_Id = eq.Chapter_Id
order by c.Ch_Sequence_ID , eq.Sequence_ID,ec.Cat_Name
End
CREATE procedure [dbo].[spGetQuestionsPerCategory](#category_Id int)
as
Begin
SELECT
eq.Question
FROM
EPQ2.Questions eq, EPQ2.Mapping_Question_Category mpq
WHERE
mpq.Question_ID_FK_1 = eq.Question_ID_PK
and mpq.Cat_ID_FK_2 = #category_Id;
End
the summary or similar example would be to select all the rows from a table and then put a filter which shows all the rows again but maybe make bold the filtered one and rest of them keep as it is.
Can't comment as I lack the reputation, so some liberties in assumption are gonna be taken and I can edit later if I made the wrong assumptions.
From my understanding you want a list of questions shown to the user, with all the questions matching the category from the dropdown to be selected.
If it's possible to change the return type from the stored procedure you could just have a sql function that returns question and whether it should be checked.
CREATE procedure [dbo].[spGetAllMapping_Question_Category](#category_Id int)
as
Begin
SELECT
mpq.UID,mpq.Question_ID_FK_1,eq.Question ,mpq.Cat_ID_FK_2, ec.Description, mpq.Valid_From,
mpq.Valid_To,c.Chapter_Name,
CASE
WHEN mpq.Cat_ID_FK_2 = #category_Id THEN 1
ELSE 0
END as 'Checked'
FROM
EPQ2.Category ec,EPQ2.Questions eq, EPQ2.Mapping_Question_Category mpq, EPQ2.Chapter c
WHERE
mpq.Question_ID_FK_1 = eq.Question_ID_PK
and mpq.Cat_ID_FK_2 = ec.Cat_ID_PK
and c.Chapter_Id = eq.Chapter_Id
order by c.Ch_Sequence_ID , eq.Sequence_ID,ec.Cat_Name
End
Bit value can be set to boolean in the questionCategoryDataAccess. I know some readers have a GetBoolean function or you can use some ternary operators.
Then you can set up an checkbox using this boolean.
#foreach (var item in Model)
{
<tr>
<td>
#if (item.Checked == true)
{
<input name="AreChecked" type="checkbox" checked="checked" value="#item.Question" /> #item.Question<br />
}
else
{
<input name="AreChecked" type="checkbox" value="#item.Question" /> #item.Question<br />
}
</td>
</tr>
}
Might be easier to use Html helpers but I followed the standard you had.
Hope this helps and if I made some wrong assumptions let me know and I'll do my best to help get the right solution.

JavaScript - Having trouble splicing an item from an array and then re-rendering that array to my page

Essentially, I'm rendering a couple of notes from a notes[] array to my page and adding a button to each note that, when clicked, will remove the note from the array using splice(), then re-render the remaining notes. The button is given an id based on the title of the note (given as input by a user), which is also given a similar id.
This is just some Vanilla JS for a personal project and after looking around this morning I've yet to find a solution that doesn't deal with Vue, Angular, or some other framework/package.
HTML
This is the relevant HTML:
<main>
<div id="container">
<form id="utilities">
<input type="text" name="userTitle" id="user-title" placeholder="Title" autocomplete="off">
<input type="text" name="userBody" id="user-body" placeholder="Body" autocomplete="off">
<div id="buttons">
<input type="submit" name="userSubmit" id="user-submit" value="Submit">
</div>
<input type="text" name="userFilter" id="user-filter" placeholder="Search" autocomplete="off">
</form>
<div id="results"></div>
</div>
</main>
JavaScript
The following JS snippets are all in order, simply broken up for readability and comments.
This is the array I'm passing to and pulling from. It takes a title, a body, an id.
const notes = [{
title: 'Grocery List',
body: 'Buy milk, eggs, and bread',
id: 'grocery-list'
},
{
title: 'Workout Routine',
body: 'running, push-ups, rowing',
id: 'workout-routine'
}
]
This is my function that's getting the title and body text from the user input. It is called in renderNotes().
const results = document.querySelector('#results');
const createElement = function(noteTitle, noteBody) {
const newNote = document.createElement('div');
const newTitle = document.createElement('h3');
const newBody = document.createElement('p');
const newButton = document.createElement('div');
newTitle.textContent = noteTitle;
newTitle.classname = 'note-title';
newBody.textContent = noteBody;
newBody.className = 'note-body';
newButton.className = 'note-button';
newButton.innerHTML = '⮿';
newButton.id = `button-${newTitle.textContent.toLowerCase()}`.replace(' ', '-');
newNote.appendChild(newTitle);
newNote.appendChild(newButton);
newNote.appendChild(newBody);
newNote.className = "note";
newNote.id = newTitle.textContent.toLowerCase().replace(' ', '-');
results.appendChild(newNote);
}
renderNotes() is simply calling createElement() on each note in that array. Then I'm calling it for the first time.
const renderNotes = function(list) {
console.log(list)
list.forEach(function(item) {
createElement(item.title, item.body)
})
}
renderNotes(notes);
This snippet seems to be where I'm failing. It should be getting each button (created during the createElement() calls) and adding an eventListener('click') to it. Then it is supposed to look through each of the notes in notes[], find the one which has a similar id to that of the button pressed, and splice() that note from the notes[] array. Then I simply want to re-render the notes.
document.querySelectorAll('.note-button').forEach(function(button) {
button.addEventListener('click', function(e) {
notes.forEach(function(note) {
if (e.target.id.includes(note.id)) {
notes.splice(notes.indexOf(note), 1)
}
renderNotes(notes)
})
})
});
Actual Results
The notes seem to be spliced from the array consistently, but my problem lies in getting them to re-render. Currently it's just removing the items and then either failing to render or is adding more copies to the page. Edit to add: I'm not receiving any errors in the console, the code is just executing properly as far as the computer is concerned. So I know it's definitely a "Problem Between Chair and Keyboard" error.
Hopefully this makes sense. I appreciate any responses.
You're calling renderNotes(notes) at each iteration not only after the array was mutated.
Try something like:
const clickedNote = notes.find(note => e.target.id.includes(note.id));
notes.splice(notes.indexOf(clickedNote), 1);
renderNotes(notes);
A better solution will be to define notes using let and then do something like this:
notes = notes.filter(note => !e.target.id.includes(note.id));
renderNotes(notes);

Form with JQuery Steps using aui:form tag in Liferay submits no data

I built a portlet and added a entity named Idea. There are two JSPs, one is the view and one the edit.
In the view there is only a button to create a new Idea and a table showing all ideas. Clicking on the button shows the edit jsp.
There is a form with two fieldsets and input stuff.
The "problem" is i cannot use the <aui:form ... stuff because it won't work with JQuery steps (or better, i cannot get it working). So i am using normal tag and also JQuery steps is providing the submit button which is only a <a href="#finish" ...>. So that wont bring the form to submit and the data being in the database.
So I tried to do it within the javascript code of the definition of jquery steps like here:
$(document).ready(function(){
var form = $("#wizard").show();
form.steps(
{
headerTag : "h3",
bodyTag : "fieldset",
transitionEffect : "slideLeft",
onFinishing: function (event, currentIndex) {
alert("Submitted!");
var data = jQuery("#wizard").serialize();
alert(data);
jQuery("#wizard").submit();
form.submit();[/b]
},
onFinished: function (event, currentIndex) {
//I tried also here..
},
});
});
But even if i declare the data explicitely it wont put it in the db.
So my idea was that the "controller" class which calls the "addIdea" function is never called.
How am I solving the problem?
Here is also my jsp code for the form part:
<aui:form id="wizard" class="wizard" action="<%= editIdeaURL %>" method="POST" name="fm">
<h3>Idea</h3>
<aui:fieldset>
<aui:input name="redirect" type="hidden" value="<%= redirect %>" />
<aui:input name="ideaId" type="hidden" value='<%= idea == null ? "" : idea.getIdeaId() %>'/>
<aui:input name="ideaName" />
</aui:fieldset>
<h3>Idea desc</h3>
<aui:fieldset>
<aui:input name="ideaDescription" />
</aui:fieldset>
<aui:button-row>
<aui:button type="submit" />
<aui:button onClick="<%= viewIdeaURL %>" type="cancel" />
</aui:button-row>
</aui:form>
Is there a way to "teach" JQuery Steps the <aui:*** tags? I tried it already while initializing the form but it won't work. To get it working using the aui tags would be great. Because otherwise the Liferay portal wont get the data or it would get it only with hacks right?
€dit: What I forgot, when I submit the form using javascript submit, it creates a new dataentry in the db but no actual data in it.
€dit2:
The editIdeaURL is referenced a bit over the form here:
<portlet:actionURL name='<%=idea == null ? "addIdea" : "updateIdea"%>'
var="editIdeaURL" windowState="normal" />
and the addIdea code looks as follows:
In the IdeaCreation class first this:
public void addIdea(ActionRequest request, ActionResponse response)
throws Exception {
_updateIdea(request);
sendRedirect(request, response);
}
Where _updateIdea() is:
private Idea _updateIdea(ActionRequest request)
throws PortalException, SystemException {
long ideaId = (ParamUtil.getLong(request, "ideaId"));
String ideaName = (ParamUtil.getString(request, "ideaName"));
String ideaDescription = (ParamUtil.getString(request, "ideaDescription"));
ServiceContext serviceContext = ServiceContextFactory.getInstance(
Idea.class.getName(), request);
Idea idea = null;
if (ideaId <= 0) {
idea = IdeaLocalServiceUtil.addIdea(
serviceContext.getUserId(),
serviceContext.getScopeGroupId(), ideaName, ideaDescription,
serviceContext);
} else {
idea = IdeaLocalServiceUtil.getIdea(ideaId);
idea = IdeaLocalServiceUtil.updateIdea(
serviceContext.getUserId(), ideaId, ideaName, ideaDescription,
serviceContext);
}
return idea;
}
And to finally put the data using IdeaLocalServiceImpl:
public Idea addIdea(
long userId, long groupId, String ideaName, String ideaDescription,
ServiceContext serviceContext)
throws PortalException, SystemException {
User user = userPersistence.findByPrimaryKey(userId);
Date now = new Date();
long ideaId =
counterLocalService.increment(Idea.class.getName());
Idea idea = ideaPersistence.create(ideaId);
idea.setIdeaName(ideaName);
idea.setIdeaDescription(ideaDescription);
idea.setGroupId(groupId);
idea.setCompanyId(user.getCompanyId());
idea.setUserId(user.getUserId());
idea.setCreateDate(serviceContext.getCreateDate(now));
idea.setModifiedDate(serviceContext.getModifiedDate(now));
super.addIdea(idea);
return idea;
}
Any ideas?

Categories