How a modal see the row's index Reactjs - javascript

I'm having difficulty on passing the index from button to button so here is my code. Tthe first one is the render loop that shows all my rows and its button the button at the delete part is calling the index from the row.
renderItem(d, i) {
return <tr key={i} >
<td> {d.Employee_ID} </td>
<td>{d.Employee_Name}</td>
<td>{d.Address }</td>
<td><center><button className ="btn btn-info" onClick={this.handleOnclick.bind(this, d.Employee_ID, d.Employee_Name, d.Address , d.Department)} data-toggle="modal" data-target="#UpdateEmployee">Edit</button></center></td>
// this part is calling button is calling the {i} or what we call the index
<td><center><button className ='btn btn-danger' onClick={this.handleOnclick.bind(this, d.Employee_ID , d.Employee_Name,i)} data-toggle="modal" data-target="#DeleteEmployee"> Delete</button></center></td>
</tr>
}
this is where it proceed to my modal
{/*Delete*/}
<div className="modal fade" id="DeleteEmployee" role="dialog">
<div className="modal-dialog">
<div className="modal-content">
<div className="modal-header">
<button type="button" className="close" data-dismiss="modal">×</button>
<h4 className="modal-title">Delete Employee</h4>
</div>
<div className="container">
<div className="modal-body">
Are you sure you want to delete {this.state.Employee_Name}?
</div>
</div>
<div className="modal-footer">
// I tried calling the index here but the modal can't see my index
<input type="submit" className ="btn btn-danger" data-dismiss="modal" onClick={this.deleteEmployee.bind(this, this.state.Employee_ID ,this.state.i)}/>
<button type="button" className="btn btn-default" data-dismiss="modal" >Close</button>
</div>
</div>
</div>
</div>
but the onclick on my modal can't see the index, because it always delete the first row
deleteEmployee(id, index) {
jQuery.support.cors = true;
fetch('http://localhost:5118/api/employeedetails/DeleteEmployeeDetail/'+ id, {
method: 'GET'
}).then(function(response) {
// history.go(0);
var jsonReturnedValue = [...this.state.jsonReturnedValue];
this.setState({jsonReturnedValue})
}).catch(function(err) {
// Error :(
});
this.state.jsonReturnedValue.splice(index, 1)
this.setState({})
}
PS: The delete works my problem was only the ajax

You are passing the emplyee ID into the bind function as a parameter, which doesn't make sense at all, what you need to do is pass the employee ID to the deleteEmployee function, like this:
onClick={() => this.deleteEmployee(d.Employee_ID , d.Employee_Name,i).bind(this)}
Also just as an extra information start using ES6's awsesome arrow function and you don't have to bind the this everytime, for instance in your case just change the above click handler to:
onClick={() => this.deleteEmployee(d.Employee_ID , d.Employee_Name,i)}
and your deleteEmployee function should look like this:
deleteEmployee = (id, index) => {
jQuery.support.cors = true;
fetch('http://localhost:5118/api/employeedetails/DeleteEmployeeDetail/'+ id, {
method: 'GET'
}).then(function(response) {
// history.go(0);
var jsonReturnedValue = [...this.state.jsonReturnedValue];
this.setState({jsonReturnedValue})
}).catch(function(err) {
// Error :(
});
this.state.jsonReturnedValue.splice(index, 1)
this.setState({})
}

for the button you should change it
<td><center><button className ='btn btn-danger' onClick={this.handleOnclick2.bind (this,d.Employee_ID,d.Employee_Name,i)} data-toggle="modal" data-target="#DeleteEmployee"> Delete</button></center></td>
and add the bind in your constructor
constructor() {
super();
this.state = { jsonReturnedValue: []}
this.handleOnclick2= this.handleOnclick2.bind(this)
}

Related

.map returning first value in array

world... again.
I'm stumped by something that should be straightforward, but right now I cant see it. I'm trying to map over a simple array and display values. Each card should have a button that opens a bs modal which should show more information on the particular array object. but instead it returns infomation only on the first object in the array.
I think there's a concept here that I'm not getting and it's a shade embarassing. Thaank's in advance for your help.
import "./styles.css";
export default function App() {
const modalInfo = [
{ name: "james", number: "1" },
{ name: "Jackie", number: "2" },
{ name: "Ariane", number: "3" },
{ name: "Mike", number: "4" }
];
return (
<>
<div className="App">
{modalInfo.map((info) => (
<div className="card">
<h1>{info.name}</h1>
<button
type="button"
class="btn btn-primary"
data-bs-toggle="modal"
data-bs-target="#staticBackdrop"
>
Show more
</button>
<div
class="modal fade"
id="staticBackdrop"
data-bs-backdrop="static"
data-bs-keyboard="false"
tabindex="-1"
aria-labelledby="staticBackdropLabel"
aria-hidden="true"
>
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="staticBackdropLabel">
#{info.number}
</h5>
<button
type="button"
class="btn-close"
data-bs-dismiss="modal"
aria-label="Close"
></button>
</div>
<div class="modal-body">{info.name}</div>
<div class="modal-footer">
<button
type="button"
class="btn btn-secondary"
data-bs-dismiss="modal"
>
Close
</button>
<button type="button" class="btn btn-primary">
Understood
</button>
</div>
</div>
</div>
</div>
</div>
))}
</div>
</>
);
}
This is the current error in console , I copied the code from sandbox and plugged it into another project with bootstrap:
Uncaught TypeError: 'querySelector' called on an object that does not
implement interface Element. findOne selector-engine.js:24
_showElement modal.js:217 show modal.js:143 y index.js:251 show backdrop.js:54 y index.js:251 r index.js:273 selector-engine.js:24:43
You must be getting some unique key error in your console.
Give a key to you card that acts a a unique id for your card.
<....
{modalInfo.map((info, index) => (
<div className="card" key={info.index}>
...>
You can give index as well as a unique id but that not correct way just for testing you can. But from what I see is the number property is incrementing by 1 as well so that's why I have kept index as the key.
id attributes must be unique in a document. You are re-using staticBackdrop in each map iteration so they're being duplicated.
When Bootstrap tries to grab the modal target by #staticBackdrop, it only gets the first one because that's what happens with repeated IDs.
Using the info.id properties from your sandbox link, try incorporating that into the id and data-bs-target attributes
{modalInfo.map((info) => (
<div className="card" key={info.id}> {/* keys are important, don't use index */}
<h1>{info.name}</h1>
<button
type="button"
className="btn btn-primary"
data-bs-toggle="modal"
data-bs-target={`#staticBackdrop_${info.id}`}
>
Show more
</button>
<div
className="modal fade"
id={`staticBackdrop_${info.id}`}
data-bs-backdrop="static"
data-bs-keyboard="false"
tabIndex="-1"
aria-labelledby={`staticBackdropLabel_${info.id}`}
aria-hidden="true"
>
{/* the rest of your markup goes here */}
</div>
</div>
))}
You also have a bunch of class attributes that should be className and a repeated id="staticBackdropLabel" that should get a similar treatment to staticBackdrop.

How to trigger bootstrap modal programatically in reactjs

Onclick of a button i need to validate some data, if it is true then i need to open modal or no. But in my condition modal is opening for every click unable to it programatically
function verifyOtp(){
if(sucsess){}
else{}
}
<button onClick={()}=>verifyOtp() data-toggle="modal" data-target="#successModal">
</button>
<div className="modal fade" id="successModal" tabindex="-1" role="dialog" aria-labelledby = "emailModalLabel" aria-hidden="true">
<div className="modal-dialog email-modal-dialog" role="document">
<div className="modal-content verify-modal-dialog">
<div className="modal-header email-modal-header">
<button type="button" className="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<p className="modal-title email-modal-title" id="emailModalLabel">Succesfull</p>
</div>
</div>
</div>
You Need to use State here is the working-class component example of a model. if you are using functional components then use useState() hook instead of this.setState() method
import React from "react";
export default class AddNewList extends React.Component {
state = {
showModal: false
};
closeModal = () => {
this.setState({ showModal: false });
};
onSave = () => {
console.log("i saved the data.");
this.setState({ showModal: false });
};
verifyOtp = () => {
//your success value
if (true) {
this.setState({ showModal: true });
}
};
render() {
return (
<>
<div>
<button onClick={this.verifyOtp} className="btn btn-primary btn-lg">
Open Modal
</button>
</div>
{this.state.showModal && (
<div className="" id="addnewlist">
<div className="modal-dialog">
<div className="modal-content">
<div className="modal-header">
<h4 className="modal-title"> Model Header</h4>
</div>
<div className="modal-body">
test
</div>
<div className="modal-footer">
<button
type="button"
className="btn btn-danger"
data-dismiss="modal"
onClick={this.closeModal}
>
Close
</button>
<button
type="button"
className="btn btn-outline-success"
onClick={this.onSave}
>
Save
</button>
</div>
</div>
</div>
</div>
)}
</>
);
}
}
Skeleton for the functional component
import React, {useState} from 'react'
const [showModel,setShowModel] = useState(false);
function AddNewList (){
closeModal = () => {
setShowModel(false);
};
onSave = () => {
setShowModel(false);
};
verifyOtp = () => {
//your success value
if (true) {
setShowModel(true);
}
};
return render();
}

How to change background image of specific div with 'onclick' function in React.JS

Thanks for helping my needy butt.
I am working with ReactJS and trying to get a div to change it's background from a color to a specific image url on click of a button in a modal.
I have tried many things and keep getting this error:
TypeError: Cannot read property 'style' of null
I successfully console.log the image URL and div ID within the onclick function, but the div styling is getting nowhere...All help is appreciated!
Here is my button
<button onClick={() => { this.changeUserBG(this.state.AlexPics[0], "one") }} className="btn btn-danger">Kaalia of the Vast</button>
here is the function I call
changeUserBG = (imageUrl, userArea) => {
let thisOne = document.getElementById(userArea);
console.log(thisOne)
thisOne.style.backgroundColor = 'red'
// document.getElementById("one").style.backgroundImage = `require(url(${imageUrl}))`;
}
Here is the div area I am trying to manipulate:
<div className="col-6" id="one">
<div className="">
<p className="lifeArea">
<button className="minusOne" onClick={() => {
this.subtractOne("playerOne") }}>-1</button>
<span id="playerOne">40</span>
<button className="plusOne" onClick={() => {
this.addOne("playerOne") }}>+1</button>
</p>
{/* Theme Modal that has ASK sub modals */}
<p className="bgCheckButton">
<button type="button" className="btn btn-primary" data-toggle="modal" data-target="#exampleModalScrollable">Theme</button>
</p>
</div>
wanna talk mtg? down for that too!
In react, you should not use getElementById or any method changing the dom.
You could have something like this:
<div style={{backgroundImage: this.state.image}}>...</div>
So whenever you do:
this.setState({ image: 'some_value.png' });
the background image will be updated automatically.
In your case, if you need to change different div background based on div ID, you could store a map in your state, something like this:
clickHandler = (divId, color) => {
this.setState(state => ({ backgroundColors: { [divId]: color, ...state.backgroundColors} }));
}
The line of code above might be hard to understand at first if you are not used to the spread operator, but what it does is actually simple: it adds a new key to map backgroundColors stored in the state.
And you would use it as such:
<div id="foo" style={{ backgroundImage: this.state.backgroundColors["foo"]}}>...</div>
You can use React ref api to get the refrence of the div and then you can change the style property of the div.
Sample Code
In Class constructor
constructor() {
this.userAreaRef = React.createRef();
}
changeUserBG = (imageUrl, userArea) => {
let thisOne = this.userAreaRef;
console.log(thisOne)
thisOne.current.style.backgroundColor = 'red'
}
Render
<div ref={this.userAreaRef} className="col-6" id="one">
<div className="">
<p className="lifeArea">
<button className="minusOne" onClick={()=> {
this.subtractOne("playerOne") }}>-1</button>
<span id="playerOne">40</span>
<button className="plusOne" onClick={()=> {
this.addOne("playerOne") }}>+1</button>
</p>
{/* Theme Modal that has ASK sub modals */}
<p className="bgCheckButton">
<button type="button" className="btn btn-primary" data-toggle="modal" data-target="#exampleModalScrollable">Theme</button>
</p>
</div>
</div>
In functional component
const someFunction = () => {
const userAreaRef = useRef();
changeUserBG = (imageUrl, userArea) => {
let thisOne = userAreaRef;
console.log(thisOne)
thisOne.current.style.backgroundColor = 'red'
}
return (
<div ref={this.userAreaRef} className="col-6" id="one">
<div className="">
<p className="lifeArea">
<button className="minusOne" onClick={()=> {
this.subtractOne("playerOne") }}>-1</button>
<span id="playerOne">40</span>
<button className="plusOne" onClick={()=> {
this.addOne("playerOne") }}>+1</button>
</p>
{/* Theme Modal that has ASK sub modals */}
<p className="bgCheckButton">
<button type="button" className="btn btn-primary" data-toggle="modal" data-target="#exampleModalScrollable">Theme</button>
</p>
</div>
</div>
);
}

How to get the id and name of an object on button click and display them in a modal in asp.net view

I have a strongly typed view in which I am looping over some objects from a database and dispaying them in a jumbobox with two buttons in it. When I click one of the buttons I have a modal popping up. I'd like to have somewhere in this modal the name and the id of the corresponding object, but I do not really know how to do this. I am a bit confused where to use c# and where javascript. I am a novice in this, obviously.
Can someone help?
This is the code I have so far. I don't have anything in relation to my question, except the code for the modal :
#model IEnumerable<eksp.Models.WorkRole>
#{
ViewBag.Title = "DisplayListOfRolesUser";
}
<div class="alert alert-warning alert-dismissable">You have exceeded the number of roles you can be focused on. You can 'de-focus' a role on this link.</div>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
var dataJSON;
$(".alert").hide();
//make the script run cuntinuosuly
$.ajax({
type: "POST",
url: '#Url.Action("checkNumRoles", "WorkRoles")',
dataType: "json",
success: successFunc,
error: errorFunc
});
function successFunc(data, status) {
if (data == false) {
$(".alert").show();
$('.btn').addClass('disabled');
//$(".btn").prop('disabled', true);
}
}
function errorFunc() {
alert('error');
}
});
</script>
#foreach (var item in Model)
{
<div class="jumbotron">
<h1>#Html.DisplayFor(modelItem => item.RoleName)</h1>
<p class="lead">#Html.DisplayFor(modelItem => item.RoleDescription)</p>
<p> #Html.ActionLink("Focus on this one!", "addWorkRoleUser", new { id = item.WorkRoleId }, new { #class = "btn btn-primary btn-lg" })</p>
<p> <button type="button" class="btn btn-default btn-lg" data-toggle="modal" data-target="#myModal">Had role in the past</button> </p>
</div>
}
<!-- Modal -->
<div id="myModal" class="modal fade" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">#Html.DisplayFor(modelItem => item.RoleName)//doesn't work</h4>
</div>
<div class="modal-body">
<p>Some text in the modal.</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Save</button>
</div>
</div>
</div>
</div>
I think your confusing the server side rendering of Razor and the client side rendering of the Modal. The modal cannot access your Model properties as these are rendered server side before providing the page to the user. This is why in your code <h4 class="modal-title">#Html.DisplayFor(modelItem => item.RoleName)//doesn't work</h4> this does not work.
What you want to do is capture the event client side in the browser. Bootstrap allows you to achieve this by allowing you to hook into events of the Modal. What you want to do is hook into the "show" event and in that event capture the data you want from your page and supply that to the Modal. In the "show" event, you have access to the relatedTarget - which is the button that called the modal.
I would go one step further and make things easier by adding what data you need to the button itself as data-xxxx attributes or to DOM elements that can be easily access via JQuery. I have created a sample for you based on what you have shown to give you an idea of how it can be achieved.
Bootply Sample
And if needed... How to specify data attributes in razor
First of all
you will need to remove the data-toggle="modal" and data-target="#myModal" from the button, as we will call it manually from JS and add a class to reference this button later, your final button will be this:
<button type="button" class="btn btn-default btn-lg modal-opener">Had role in the past</button>
Then
In your jumbotron loop, we need to catch the values you want to show later on your modal, we don't want to show it, so we go with hidden inputs:
<input type="hidden" name="ID_OF_MODEL" value="#item.WorkRoleId" />
<input type="hidden" name="NAME_OF_MODEL" value="#item.RoleName" />
For each information you want to show, you create an input referencing the current loop values.
Now you finally show the modal
Your document.ready function will have this new function:
$('.modal-opener').on('click', function(){
var parent = $(this).closest('.jumbotron');
var name = parent.find('input[name="NAME_OF_MODEL"]').val();
var id = parent.find('input[name="ID_OF_MODEL"]').val();
var titleLocation = $('#myModal').find('.modal-title');
titleLocation.text(name);
// for each information you'll have to do like above...
$('#myModal').modal('show');
});
It simply grab those values we placed in hidden inputs.
Your final code
#model IEnumerable<eksp.Models.WorkRole>
#{
ViewBag.Title = "DisplayListOfRolesUser";
}
<div class="alert alert-warning alert-dismissable">You have exceeded the number of roles you can be focused on. You can 'de-focus' a role on this link.</div>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
var dataJSON;
$(".alert").hide();
//make the script run cuntinuosuly
$.ajax({
type: "POST",
url: '#Url.Action("checkNumRoles", "WorkRoles")',
dataType: "json",
success: successFunc,
error: errorFunc
});
function successFunc(data, status) {
if (data == false) {
$(".alert").show();
$('.btn').addClass('disabled');
//$(".btn").prop('disabled', true);
}
}
function errorFunc() {
alert('error');
}
$('.modal-opener').on('click', function(){
var parent = $(this).closest('.jumbotron');
var name = parent.find('input[name="NAME_OF_MODEL"]').val();
var id = parent.find('input[name="ID_OF_MODEL"]').val();
var titleLocation = $('#myModal').find('.modal-title');
titleLocation.text(name);
// for each information you'll have to do like above...
$('#myModal').modal('show');
});
});
</script>
#foreach (var item in Model)
{
<div class="jumbotron">
<input type="hidden" name="ID_OF_MODEL" value="#item.WorkRoleId" />
<input type="hidden" name="NAME_OF_MODEL" value="#item.RoleName" />
<h1>#Html.DisplayFor(modelItem => item.RoleName)</h1>
<p class="lead">#Html.DisplayFor(modelItem => item.RoleDescription)</p>
<p> #Html.ActionLink("Focus on this one!", "addWorkRoleUser", new { id = item.WorkRoleId }, new { #class = "btn btn-primary btn-lg" })</p>
<p> <button type="button" class="btn btn-default btn-lg" data-toggle="modal" data-target="#myModal">Had role in the past</button> </p>
</div>
}
<!-- Modal -->
<div id="myModal" class="modal fade" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">#Html.DisplayFor(modelItem => item.RoleName)//doesn't work</h4>
</div>
<div class="modal-body">
<p>Some text in the modal.</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Save</button>
</div>
</div>
</div>

How to add many functions in ONE ng-click?

I've be looking for how to execute this but I can't find anything related so far, :(
I could nest both functions yes but I'm just wondering if this is possible?
I'd like to do this literally:
<td><button class="btn" ng-click="edit($index) open()">Open me!</button></td>
My JS code at the moment:
$scope.open = function () {
$scope.shouldBeOpen = true;
};
$scope.edit = function(index){
var content_1, content_2;
content_1 = $scope.people[index].name;
content_2 = $scope.people[index].age;
console.log(content_1);
};
I'd like to call two functions with just one click, how can I do this in angularJS?
I thought it'd be straight forward like in CSS when you add multiple classes...but it's not :(
You have 2 options :
Create a third method that wrap both methods. Advantage here is that you put less logic in your template.
Otherwise if you want to add 2 calls in ng-click you can add ';' after edit($index) like this
ng-click="edit($index); open()"
See here : http://jsfiddle.net/laguiz/ehTy6/
You can call multiple functions with ';'
ng-click="edit($index); open()"
A lot of people use (click) option so I will share this too.
<button (click)="function1()" (click)="function2()">Button</button>
The standard way to add Multiple functions
<button (click)="removeAt(element.bookId); openDeleteDialog()"> Click Here</button>
or
<button (click)="removeAt(element.bookId)" (click)="openDeleteDialog()"> Click Here</button>
Try this:
Make a collection of functions
Make a function that loops through and executes all the functions in the collection.
Add the function to the html
array = [
function() {},
function() {},
function() {}
]
function loop() {
array.forEach(item) {
item()
}
}
ng - click = "loop()"
Follow the below
ng-click="anyFunction()"
anyFunction() {
// call another function here
anotherFunction();
}
<!-- Button trigger modal -->
<button type="button" (click)="open(content)" style="position: fixed; bottom: 0; right: 130px;"
class="btn col-sm-1 btn-Danger" >
Reject
</button>
<ng-template #content let-modal>
<div class="modal-header">
<h4 class="modal-title" id="modal-basic-title">Profile update</h4>
<button type="button" class="btn-close" aria-label="Close" (click)="modal.dismiss('Cross click')"></button>
</div>
<div class="modal-body">
<div class="mb-3">
<label class="bg-danger text-light" for="Reject">Reason For reject</label>
<textarea matInput placeholder=" Reject" [(ngModel)]="asset_note">{{note}}</textarea>
</div>
</div>
<div class="modal-footer">
<!-- -->
<button type="button" class="btn btn-outline-dark" (click)="reject();modal.close('Save click') ">Save</button>
</div>
</ng-template>
**.ts file**
open(content: any) {
this.modalService.open(content, {ariaLabelledBy: 'modal-basic-title'}).result.then((result) => {
this.closeResult = `Closed with: ${result}`;
}, (reason) => {
this.closeResult = `Dismissed ${this.getDismissReason(reason)}`;
});
}
private getDismissReason(reason: any): string {
if (reason === ModalDismissReasons.ESC) {
return 'by pressing ESC';
} else if (reason === ModalDismissReasons.BACKDROP_CLICK) {
return 'by clicking on a backdrop';
} else {
return `with: ${reason}`;
}
}
close()
{
this.getDismissReason(ModalDismissReasons.ESC);
}
Which of the following is best practice (option1 or option2)
<button (click)="removeAt(element.bookId); openDeleteDialog()"> Click Here
<button (click)="removeAt(element.bookId)" (click)="openDeleteDialog()"> Click Here
ng-click "$watch(edit($index), open())"

Categories