how to get value of column in react - javascript

I have table column like this which have value that comes from my reducer. the same column has increment/decrement button. so when use clicks on button I have to get value from that <td> and trigger my action. I am searching here but its for input text which have event onChange. please anyone let me know how to do this?
Here is my <td> column:
<td>
{this.props.prog}%
<button type="button" className="btn btn-danger">
<span className="glyphicon glyphicon-arrow-up" />
</button>
<button type="button" className="btn btn-danger">
<span className="glyphicon glyphicon-arrow-down" />
</button>
</td>
EDIT 1:
I have tried something basically my onClick triggered properly but I am not able to pass the value
<td>
<button type="button" className="btn btn-danger" onClick={this.props.resetGrowth}>Reset</button>
{this.props.prog}%
<button type="button" className="btn btn-danger" onClick = {(event) => this.props.updated(this.props.prog) }>
<span className="glyphicon glyphicon-arrow-up"/>
</button>
<button type="button" className="btn btn-danger">
<span className="glyphicon glyphicon-arrow-down"/>
</button>
</td>
it will pass to it this component
<Table updated={value => this.props.udated(value)}/>
this is my container it triggers value
<VolumeComponent
udated = {(value) => updated(value)}/>
const mapDispatchToProps= (dispatch) => (
bindActionCreators({updated},dispatch)
)

Since you are using a reducer I am guessing you are using redux. If {this.props.prog}is your value, you could use this in the OnClick function you pass to the increase/ decrease buttons. For example:
handleDecrease(){
const newValue = this.props.prog + 1;
this.props.updateValue(newValue)
}
handleIncrease(){
const newValue = this.props.prog - 1;
this.props.updateValue(newValue)
}
render(){
return (
...
<button onClick={this.handleIncrease}/>
);
}

Related

my sorting function sortResult is not working not working

i am trying to make a function that sorts the data by id or by name but its not working i need props department name and departmnet id to sort which i have given still its not working.
when is console prop it shows a blank and for asc it shows true or false
here is the code (i have removed some parts of code which r not related to sorting):
const Department = () => {
let [department, setDepartment] = useState([])
let [filteredDepartment, setFilteredDepartment] = useState([])
let [values, setValues] = useState({
modalTitle: '',
departmentName: '',
departmentId: 0,
departmentIdFilter: "",
departmentNameFilter: "",
departmentsWithoutFilter: [],
})
useEffect (() => {
getDepartments()
}, [])
let sortResult = (prop, asc) => {
console.log(prop)
console.log(asc)
const sortedData = filteredDepartment.sort(function(a, b) {
if(asc){
return (a[prop]>b[prop]) ? 1 : ((a[prop] < b[prop]) ? - 1 : 0)
}
else{
return (b[prop]>a[prop]) ? 1 : ((b[prop] < a[prop]) ? - 1 : 0)
}
})
setDepartment(sortedData)
}
let getDepartments = async () => {
let response = await fetch (variables.API_URL + "department")
let data = await response.json()
setDepartment(data)
setFilteredDepartment(data)
}
return (
<div>
<button type="button" className="btn btn-primary m-2 float-end" data-bs-toggle="modal" data-bs-target="#exampleModal" onClick={() => addClick()}>Add Department</button>
<table className="table table-striped">
<thead>
<tr>
<th>
<div className="d-flex flex-row">
<input className="form-control m-2" onChange={(e) => {changeDepartmentIdFilter(e)}} placeholder='Filter' />
<button type="button" className="btn btn-light" onClick={(() =>sortResult(values.departmentId, true))}>
sort a
</button>
<button type="button" className="btn btn-light" onClick={() => sortResult(values.departmentId, false)}>
sort b
</button>
</div>
DepartmentId
</th>
<th>
<div className="d-flex flex-row">
<input className="form-control m-2" onChange={(e) => {changeDepartmentNameFilter(e)}} placeholder='Filter' />
<button type="button" className="btn btn-light" onClick={() => sortResult(values.departmentName, true)}>
sort a
</button>
<button type="button" className="btn btn-light" onClick={() => sortResult(values.departmentName, false)}>
sort b
</button>
</div>
DepartmentName
</th>
<th>
Options
</th>
</tr>
</thead>
<tbody>
{department.map((dep) =>
<tr key={dep.DepartmentId}>
<td>{dep.DepartmentId}</td>
<td>{dep.DepartmentName}</td>
<td>
{/* >>>>>>EDIT BUTTON<<<<<< */}
<button type="button" className="btn btn-light mr-1" data-bs-toggle="modal" data-bs-target="#exampleModal" onClick={() => editClick(dep)}>
</button>
{/* >>>>>>>DELETE BUTTON<<<<<<<<<<< */}
<button type="button" className="btn btn-light mr-1" onClick={() => deleteClick(dep.DepartmentId)}>
</button>
</td>
</tr>
)}
</tbody>
</table>
</div>
)}
sort is an in-place sort, meaning it mutates the array it operates over. It also happens to be the filteredDepartment state. You mutate filteredDepartment and save the current state reference into sortedData and then save that back into state. A new array reference is never created.
Copy the filteredDepartment array first, then sort the elements. Array.prototype.slice works well here to shallow copy the array into a new reference.
const sortResult = (prop, asc) => {
const sortedData = filteredDepartment.slice().sort(function(a, b) {
if (asc) {
return (a[prop] > b[prop]) ? 1 : ((a[prop] < b[prop]) ? - 1 : 0)
} else {
return (b[prop] > a[prop]) ? 1 : ((b[prop] < a[prop]) ? - 1 : 0)
}
});
setDepartment(sortedData);
}
Update - fix the sorting properties
Sorting by the DepartmentId property:
<button
type="button"
className="btn btn-light"
onClick={() => sortResult("DepartmentId", true)}
>
sort a
</button>
<button
type="button"
className="btn btn-light"
onClick={() => sortResult("DepartmentId", false)}
>
sort b
</button>
Sorting by the DepartmentName property:
<button
type="button"
className="btn btn-light"
onClick={() => sortResult("DepartmentName", true)}
>
sort a
</button>
<button
type="button"
className="btn btn-light"
onClick={() => sortResult("DepartmentName", false)}
>
sort b
</button>

How to change the dropdown value, if we have more records without having break using angular8

I have used Angular8 in my project, here if i have 2-3 records then Previous and Next works fine, but if i have more records, then when i click on previous/next, then it break the code and struck in the middle. Can anyone help, how to solve this issue. I have attached working demo of my code.
TS:
public changeDropdown(value) {
const entry = this.dropdownValue.findIndex(x => x.noteId === parseInt(value));
this.selectedDropdownValue = this.dropdownValue[entry].noteId;
}
public previousNextValue(value) {
let previousValue = this.selectedDropdownValue;
previousValue = value ? ++previousValue : --previousValue;
this.changeDropdown(previousValue);
} 
HTML:
<div class="card-footer text-right">
<button class="btn btn-outline-primary" type="button" (click)="previousNextValue(false)"
[disabled]="selectedDropdownValue<=1"><i class="fas fa-chevron-left"></i>
Previous</button>
<button class="btn btn-outline-primary ml-1" type="button" (click)="previousNextValue(true)"
[disabled]="selectedDropdownValue==dropdownValue.length">Next <i class="fas fa-chevron-right"></i></button>
</div>
DEMO
You need to refactor your logic from value to index of array like
export class AppComponent {
selectedDropdownValue:number = 0;
selectedIndex: number = -1;
public dropdownValue = []; // data
public previousNextValue(selectedIndex) {
this.selectedIndex = selectedIndex;
this.selectedDropdownValue = this.dropdownValue[selectedIndex].noteId;
}
public changeDropdown(selectedDropdownValue){
this.selectedDropdownValue = selectedDropdownValue;
this.selectedIndex = this.dropdownValue.findIndex(x => x.noteId === parseInt(selectedDropdownValue));
}
}
And your view for next and previous will be like
<select class="custom-select w-100" name="noteTypeId" (change)="changeDropdown($event.target.value)" [value]="selectedDropdownValue">
<option value="0" selected disabled>Select Note Details</option>
<option *ngFor="let notesItem of dropdownValue" [value]="notesItem.noteId">
{{notesItem.dropdownSubject}}
</option>
</select>
<div class="card-footer text-right">
<button class="btn btn-outline-primary" type="button" (click)="previousNextValue(selectedIndex - 1)"
[disabled]="selectedIndex < 1"><i class="fas fa-chevron-left"></i>
Previous</button>
<button class="btn btn-outline-primary ml-1" type="button" (click)="previousNextValue(selectedIndex + 1)"
[disabled]="selectedIndex >= dropdownValue.length - 1">Next <i class="fas fa-chevron-right"></i></button>
</div>
DEMO
The problem is that you are looking for an ID that doesnt exist, and also you are using the same Variable for value and for The index, wich is causing troubles, you have to create another variable for setting the previousValue. Here's an example.
selectedDropdownValue:number = 0;
globalPreviousValue: number = 0;
public dropdownValue = [
{"noteId":1,"noteTypeId":1,"noteTypeName":null,"noteSubject":"subject -1","createdDate":"2020-08-07T15:21:48.71","createdBy":"Admin","noteText":null,"dropdownSubject":"08/07/2020 Admin subject -1"},{"noteId":2,"noteTypeId":2,"noteTypeName":null,"noteSubject":"subject -2 test","createdDate":"2020-08-07T15:25:38.553","createdBy":"Admin","noteText":null,"dropdownSubject":"08/07/2020 Admin subject -2 test"},{"noteId":3,"noteTypeId":2,"noteTypeName":null,"noteSubject":"subject -3 test","createdDate":"2020-08-11T11:26:36.007","createdBy":"Admin","noteText":null,"dropdownSubject":"08/11/2020 Admin subject -3 test"},{"noteId":10,"noteTypeId":3,"noteTypeName":null,"noteSubject":"test","createdDate":"2020-08-12T11:50:14.653","createdBy":"Admin","noteText":null,"dropdownSubject":"08/12/2020 Admin test"},{"noteId":11,"noteTypeId":5,"noteTypeName":null,"noteSubject":"tested","createdDate":"2020-08-12T14:36:43.41","createdBy":"Admin","noteText":null,"dropdownSubject":"08/12/2020 Admin tested"},
{"noteId":12,"noteTypeId":135,"noteTypeName":"Email sent to Agent","noteSubject":"test","createdDate":"2020-08-12T17:25:15.71","createdBy":"Admin","noteText":null,"dropdownSubject":"08/12/2020 Admin test"},
{"noteId":13,"noteTypeId":136,"noteTypeName":"Fax to Agent","noteSubject":"tested","createdDate":"2020-08-12T17:29:59.97","createdBy":"Admin","noteText":null,"dropdownSubject":"08/12/2020 Admin tested"}]
public changeDropdown(value) {
this.globalPreviousValue = value
this.selectedDropdownValue = this.dropdownValue[value].noteId;
}
public previousNextValue(value) {
let previousValue = this.globalPreviousValue;
previousValue = value ? ++previousValue : --previousValue;
this.changeDropdown(previousValue);
} 
Also Change the Validation in your HTML in order work as desired.
<div class="card-footer text-right">
<button class="btn btn-outline-primary" type="button" (click)="previousNextValue(false)"
[disabled]="globalPreviousValue<=1"><i class="fas fa-chevron-left"></i>
Previous</button>
<button class="btn btn-outline-primary ml-1" type="button" (click)="previousNextValue(true)"
[disabled]="globalPreviousValue==dropdownValue.length-1">Next <i class="fas fa-chevron-right"></i></button>
</div>
Working Demo

How to concat number to a div?

I am making a calculator with HTML, CSS, and JS. Currently, I want a number to be concatenated to the output everytime I click a number button. Does anyone know how to do this because my code isn't working. The console keeps returning output.concat is not a function
const numbers = document.querySelectorAll("[data-number]");
numbers.forEach(number => {
number.addEventListener("click", () => {
output.concat(number);
})
})
<div>
<div data-output></div>
<button data-clear>C</button>
<button data-operator>/</button>
<button data-number>7</button>
<button data-number>8</button>
<button data-number>9</button>
<button data-operator>*</button>
<button data-number>4</button>
<button data-number>5</button>
<button data-number>6</button>
<button data-operator>-</button>
<button data-number>1</button>
<button data-number>2</button>
<button data-number>3</button>
<button data-operator>+</button>
<button data-number>0</button>
<button data-number>.</button>
<button data-equals>=</button>
</div>
You need to define output, as currently it is undefined. Do it like this:
const output = document.querySelector("[data-output]");
And then, you must treat it like an element, not like a string. The same is true for the number variable: it is not a string (nor number), but a button element. So read and add content using the textContent property on both involved elements:
output.textContent += number.textContent;
NB: You have an error in your first line. It needs a closing ] in the selector:
const numbers = document.querySelectorAll("[data-number]");
Code:
const output = document.querySelector("[data-output]");
const numbers = document.querySelectorAll("[data-number]");
numbers.forEach(number => {
number.addEventListener("click", () => {
output.textContent += number.textContent;
})
})
<div>
<div data-output></div>
<button data-clear>C</button>
<button data-operator>/</button>
<button data-number>7</button>
<button data-number>8</button>
<button data-number>9</button>
<button data-operator>*</button>
<button data-number>4</button>
<button data-number>5</button>
<button data-number>6</button>
<button data-operator>-</button>
<button data-number>1</button>
<button data-number>2</button>
<button data-number>3</button>
<button data-operator>+</button>
<button data-number>0</button>
<button data-number>.</button>
<button data-equals>=</button>
</div>
I probably won't take this approach but building on your code you probably want something like
const numbers = document.querySelectorAll("[data-number]");
const operator = document.querySelectorAll("[data-operator]");
const clear = document.getElementById("clear");
const output = document.getElementById("output");
resu=""
numbers.forEach(number => {
number.addEventListener("click", () => {
resu+=number.textContent
output.textContent=resu
})
})
operator.forEach(op => {
op.addEventListener("click", () => {
if(output.textContent.charAt(output.textContent.length-1)===op.textContent) return
else {resu+=op.textContent
output.textContent=resu}
})
})
clear.addEventListener("click",()=>{
output.textContent=""
})
<div>
<div data-output></div>
<button data-clear id="clear">C</button>
<button data-operator>/</button>
<button data-number>7</button>
<button data-number>8</button>
<button data-number>9</button>
<button data-operator>*</button>
<button data-number>4</button>
<button data-number>5</button>
<button data-number>6</button>
<button data-operator>-</button>
<button data-number>1</button>
<button data-number>2</button>
<button data-number>3</button>
<button data-operator>+</button>
<button data-number>0</button>
<button data-number>.</button>
<button data-equals>=</button>
</div>
<div id="output">#######</div>

parameters passed to function is not working

I generated a random number called listingid in function createpost and pass it as an input to function showproductmodal as shown below
function creatpost(){
var index;
splitinput.forEach((num, index) => {
var listingid = (Date.now().toString(36) + Math.random().toString(36).substr(2, 5)).toUpperCase()
console.log(index)
return CatalogueDB.ref( splitinput[index]).once('value').then(function(snapshot) {
var resultcard = `
<form id="myform${index}">
<tr class="tr-shadow">
<td>
<button type="button" class="btn btn-primary btn-md" onclick="postitem(${key},${index},${listingid});">Submit</button>
</td>
</tr>
</form>
`
container.innerHTML += resultcard;
})
.catch(function(error) {
container.innerHTML += "";
var errorcard = `
<form id="myform${index}">
<tr class="tr-shadow">
<td style="width: 90px;">
<div id="ItemID${index}">${splitinput[index]}
</div>
<div>
<br>
<button type="button" class="btn btn-secondary mb-1 btn-sm" data-toggle="modal" data-target="#productModal" onclick="showproductmodal(${splitinput[index]},${index},${listingid})">
Add Photos
</button>
</div>
</td>
<td>
<button type="button" class="btn btn-primary btn-md" onclick="postitem(${splitinput[index]},${index},${listingid})">Submit</button>
</td>
</tr>
</form>
`
container.innerHTML += errorcard;
})
});
})
function showproductmodal(id, index, listingid) {
console.log(id,index)
}
the problem now is whenever the button is clicked which triggers showproductmodal it says lisitingid is undefined
this is the console error output
index.html:1 Uncaught ReferenceError: JJLQ23008PJX0 is not defined
at HTMLButtonElement.onclick (index.html:1)
this is the sample parameters passed to the showproductmodal retrieved from the console
showproductmodal(42,0,JJLQ23008PJX0)
why is the listingid causing error even when it has been passed to the function? How do I correct this so that I can retrieve listingid in showproductmodal?
If the listingid is not a variable with the name JJLQ23008PJX0 it will throw an error.
Generally one need to make such id/value be treated as a string, and enclose it in quotes, likes this, where I added single quote's '
onclick="postitem(${splitinput[index]},${index},'${listingid}')"
Some value types works though, as numbers, the boolean keywords true/false, etc.,
You need to quote the random string:
<button type="button" class="btn btn-primary btn-md" onclick="postitem(${key},${index},'${listingid}');">Submit</button>

Deleting dynamic input fields in Vue

Noob question but I can get fields to render in Vue but not sure how to delete my fields. I added an index option in the v-for directives but not sure what to do after that. Thanks!
Here is a working JSFiddle: https://jsfiddle.net/xu55npkn/
<body>
<div id="app"></div>
<script>
const createNewOption = () => {
return {
text: '',
isAnswer: false
}
}
const createNewQuestion = () => {
return {
text: '',
options: [createNewOption()]
}
}
var vm = new Vue({
el: '#app',
template: `<div class="quiz-builder container">
<div v-for="question in questions">
<div class="input-group">
<input type="text" class="form-control" v-model="question.text" placeholder="Enter a question">
<span class="input-group-btn">
<button class="btn btn-danger" type="button">X</button>
</span>
<span class="input-group-btn">
<button class="btn btn-secondary" type="button" #click="addOption(question)">Add an option</button>
</span>
</div>
</br>
<div class="input-group" v-for="(option, index) in question.options" style="margin-bottom: 20px">
<span class="input-group-addon">
<input type="checkbox" v-model="option.isAnswer">
</span>
<input type="text" class="form-control" v-model="option.text" placeholder="Enter an option">
<span class="input-group-btn">
<button class="btn btn-danger" type="button">X</button>
</span>
</div></br>
</div>
<button class="btn btn-default" #click="addQuestion" :disabled="questions.length >= 5 ? true : false">
Add another question
</button>
<button class="btn btn-primary" style="background-color: #ffcc00; border: #ffcc00">
Create quiz
</button>
</div>`,
data () {
return {
questions: [createNewQuestion()],
showQuestions: false,
}
},
methods: {
addQuestion () {
this.questions.push(createNewQuestion())
},
removeQuestion (index) {
this.questions.shift(index)
},
addOption (question) {
question.options.push(createNewOption())
}
}
})
</script>
Based on your updated question, you have already solved for removing questions, although yev's answer is a much better way for removing questions.
To remove options, you need to add a new handler for removeOption that takes in both the question (which you are iterating over) and the option (which you are iterating over. Vue handles both of these scenarios for you. You can then find the index of the option and splice the array. See this fiddle.
template:
<button class="btn btn-danger" type="button" #click="removeOption(question, option)">
X
</button>
component:
removeOption (question, option) {
var index = question.options.indexOf(option);
if (index > -1) {
question.options.splice(index, 1);
}
}
Your delete button should look like:
<div v-for="(question, i) in questions">
<div>
<input v-model="question.text">
<span>
<button #click=removeQuestion(i)>X</button>
</span>
<span>
<button #click="addOption(question)">Add an option</button>
</span>
</div>
</div>
Notice I've added i (index) in your for loop and click handler for X button.
Your remove function will look like:
removeQuestion (index) {
this.questions.splice(index, 1);
}
Array.shift will remove only first item in the array which is not exactly what you want :)

Categories