Nuevo en el desarrollo de Bootstrap y FE en general. Tengo la siguiente página que presenta al usuario una tabla, y cada fila de la tabla tiene un botón " Cambiar " así:
Cuando el usuario hace clic en el botón de cambio, ve un modal como este:
Luego pueden cambiar el valor de la configuración y hacer clic en el botón Actualizar , donde quiero que una publicación de AJAX envíe algo de JSON a una URL determinada.
Aquí está mi mejor intento de eso:
<!DOCTYPE html> <html lang="en" xmlns="http://www.w3.org/1999/xhtml"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"/> <meta name="viewport" content="width=device-width, initial-scale=1"/> <meta name="description" content=""> <meta name="author" content=""> <title>My App</title> <!-- Bootstrap core CSS --> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"> </head> <body> <!-- Navigation --> <nav class="navbar navbar-expand-lg navbar-dark bg-dark static-top"> <div class="container"> <a class="navbar-brand" href="/">My App</a> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarResponsive"> <ul class="navbar-nav ml-auto"> <li class="nav-item"> <a class="nav-link" href="/fizzes">Fizzes</a> </li> <li class="nav-item"> <a class="nav-link" href="/buzzes">Buzzes</a> </li> </ul> </div> </div> </nav> <div class="container"> <div class="row"> <div class="col-md-4 mt-5"> <h3><span>Configurations</span></h3> <table class="table"> <thead> <tr> <th scope="col">Config</th> <th scope="col">Value</th> <th scope="col">Actions</th> </tr> </thead> <tbody> <tr> <td >type</td> <td >EXCEL</td> <td><button type="button" class="btn btn-primary" data-toggle="modal" data-target="#changeModal" data-currval="EXCEL" data-config="type">Change</button></td> </tr> <tr> <td >fizz</td> <td >1</td> <td><button type="button" class="btn btn-primary" data-toggle="modal" data-target="#changeModal" data-currval="1" data-config="fizz">Change</button></td> </tr> </tbody> </table> <button>Config History</button> </div> </div> </div> <div class="modal fade" id="changeModal" tabindex="-1" role="dialog" aria-labelledby="changeModalLabel" aria-hidden="true"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title" id="changeModalLabel">Change config value</h5> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button> </div> <div class="modal-body"> <form> <div class="form-group"> <label for="current-value" class="col-form-label">Current value:</label> <input type="text" class="form-control" id="current-value"/> </div> <div class="form-group"> <label for="new-value" class="col-form-label">New value:</label> <textarea class="form-control" id="new-value"></textarea> </div> </form> </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button> <button type="button" id="btnUpdate" class="btn btn-primary">Update</button> </div> </div> </div> </div> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script> <script type="text/javascript"> $('#changeModal').on('show.bs.modal', function (event) { var button = $(event.relatedTarget); var configName = button.data('config'); var currVal = button.data('currval'); var modal = $(this); modal.find('.modal-title').text('Change value for ' + configName); modal.find('.modal-body input').val(currVal); }); $('#btnUpdate').click(function (event) { var button = $(event.relatedTarget); var modal = $(this); var url = '/fizzes/abc123/buzzes/abc235'; var configName = button.data('config'); var newVal = modal.find('#new-value').text; $.post( url, { [configName]: newVal }, alert("update made") ) }); </script> </body> </html> Cuando ejecuto esto en un navegador, hago clic en "Cambiar", actualizo un valor y hago clic en "Actualizar", aparece la ventana emergente de alert("update made") , pero en la pestaña Red de herramientas para desarrolladores no veo un AJAX POST disparando, y en su lugar veo el siguiente error:
Uncaught TypeError: Cannot read property 'length' of undefined at $ (jquery.min.js:2) at text (jquery.min.js:2) at i (jquery.min.js:2) at Dt (jquery.min.js:2) at Function.S.param (jquery.min.js:2) at Function.ajax (jquery.min.js:2) at Function.S.<computed> [as post] (jquery.min.js:2) at HTMLButtonElement.<anonymous> (abc235:121) at HTMLButtonElement.dispatch (jquery.min.js:2) at HTMLButtonElement.v.handle (jquery.min.js:2) En el lado del servidor, tampoco veo que se reciba ninguna solicitud. Me di cuenta de que, en mi IDE, cuando paso el cursor sobre la sección JSON [configName] de la publicación de AJAX, veo el siguiente error:
" Los nombres de propiedad calculados no son compatibles con la versión actual de JavaScript "
Así que traté de cambiar eso a:
$.post( url, { configName: newVal }, alert("update made") )Pero el problema persiste. ¿Alguien puede detectar dónde me estoy equivocando?
Lo siento, no pude hacerlo en jQuery, pero aquí hay una solicitud AJAX que debería reemplazar toda su solicitud POST en la parte inferior:
function sendData(url, object) { const formdata = new FormData(); for ( let key in object ) { formdata.append(key, object[key]); } const http = new XMLHttpRequest(); return new Promise(resolve => { http.onreadystatechange = function () { if (this.readyState === 4 && this.status === 200) { resolve(this.responseText); } }; http.open("POST", url, true); http.send(formdata); }); } //object is post information sendData(url, { [configName]: newVal }).then(response => alert("Update made")); //configName should be a stringSupongo que el modal.find no cumple el propósito aquí. No pude encontrar la función de modal para leer el valor, así que usé la función jquery .val().
var newVal = $('#new-value').val();Espero que esto funcione para usted
<!DOCTYPE html> <html lang="en" xmlns="http://www.w3.org/1999/xhtml"> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"/> <meta name="viewport" content="width=device-width, initial-scale=1"/> <meta name="description" content=""> <meta name="author" content=""> <title>My App</title> <!-- Bootstrap core CSS --> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous"> </head> <body> <!-- Navigation --> <nav class="navbar navbar-expand-lg navbar-dark bg-dark static-top"> <div class="container"> <a class="navbar-brand" href="/">My App</a> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation"> <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarResponsive"> <ul class="navbar-nav ml-auto"> <li class="nav-item"> <a class="nav-link" href="/fizzes">Fizzes</a> </li> <li class="nav-item"> <a class="nav-link" href="/buzzes">Buzzes</a> </li> </ul> </div> </div> </nav> <div class="container"> <div class="row"> <div class="col-md-4 mt-5"> <h3><span>Configurations</span></h3> <table class="table"> <thead> <tr> <th scope="col">Config</th> <th scope="col">Value</th> <th scope="col">Actions</th> </tr> </thead> <tbody> <tr> <td >type</td> <td >EXCEL</td> <td><button type="button" class="btn btn-primary" data-toggle="modal" data-target="#changeModal" data-currval="EXCEL" data-config="type">Change</button></td> </tr> <tr> <td >fizz</td> <td >1</td> <td><button type="button" class="btn btn-primary" data-toggle="modal" data-target="#changeModal" data-currval="1" data-config="fizz">Change</button></td> </tr> </tbody> </table> <button>Config History</button> </div> </div> </div> <div class="modal fade" id="changeModal" tabindex="-1" role="dialog" aria-labelledby="changeModalLabel" aria-hidden="true"> <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title" id="changeModalLabel">Change config value</h5> <button type="button" class="close" data-dismiss="modal" aria-label="Close"> <span aria-hidden="true">×</span> </button> </div> <div class="modal-body"> <form> <div class="form-group"> <label for="current-value" class="col-form-label">Current value:</label> <input type="text" class="form-control" id="current-value"/> </div> <div class="form-group"> <label for="new-value" class="col-form-label">New value:</label> <textarea class="form-control" id="new-value"></textarea> </div> </form> </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button> <button type="button" id="btnUpdate" class="btn btn-primary">Update</button> </div> </div> </div> </div> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous"></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous"></script> <script type="text/javascript"> $('#changeModal').on('show.bs.modal', function (event) { var button = $(event.relatedTarget); var configName = button.data('config'); var currVal = button.data('currval'); var modal = $(this); modal.find('.modal-title').text('Change value for ' + configName); modal.find('.modal-body input').val(currVal); }); $('#btnUpdate').click(function (event) { var button = $(event.relatedTarget); var modal = $(this); var url = '/fizzes/abc123/buzzes/abc235'; var configName = button.data('config'); var newVal = $('#new-value').val(); console.log(newVal) $.post( url, { [configName]: newVal }, alert("update made") ) }); </script> </body> </html>Todo lo que realmente necesitaba arreglar eran sus selectores al enviar el cambio
var button = $(event.relatedTarget);para
var element = $('input#current-value');y cambiando
var configName = button.data('config'); var newVal = modal.find('#new-value').text; para
var configName = element.val(); var newVal = $('textarea#new-value').val();Entonces, al final, este es el aspecto que debería tener su código y debería arreglarse
<!DOCTYPE html> <html lang="en" xmlns="http://www.w3.org/1999/xhtml"> <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <meta name="description" content="" /> <meta name="author" content="" /> <title>My App</title> <!-- Bootstrap core CSS --> <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous" /> </head> <body> <!-- Navigation --> <nav class="navbar navbar-expand-lg navbar-dark bg-dark static-top"> <div class="container"> <a class="navbar-brand" href="/">My App</a> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarResponsive" aria-controls="navbarResponsive" aria-expanded="false" aria-label="Toggle navigation" > <span class="navbar-toggler-icon"></span> </button> <div class="collapse navbar-collapse" id="navbarResponsive"> <ul class="navbar-nav ml-auto"> <li class="nav-item"> <a class="nav-link" href="/fizzes">Fizzes</a> </li> <li class="nav-item"> <a class="nav-link" href="/buzzes">Buzzes</a> </li> </ul> </div> </div> </nav> <div class="container"> <div class="row"> <div class="col-md-4 mt-5"> <h3><span>Configurations</span></h3> <table class="table"> <thead> <tr> <th scope="col">Config</th> <th scope="col">Value</th> <th scope="col">Actions</th> </tr> </thead> <tbody> <tr> <td>type</td> <td>EXCEL</td> <td> <button type="button" class="btn btn-primary" data-toggle="modal" data-target="#changeModal" data-currval="EXCEL" data-config="type" > Change </button> </td> </tr> <tr> <td>fizz</td> <td>1</td> <td> <button type="button" class="btn btn-primary" data-toggle="modal" data-target="#changeModal" data-currval="1" data-config="fizz" > Change </button> </td> </tr> </tbody> </table> <button>Config History</button> </div> </div> </div> <div class="modal fade" id="changeModal" tabindex="-1" role="dialog" aria-labelledby="changeModalLabel" aria-hidden="true" > <div class="modal-dialog" role="document"> <div class="modal-content"> <div class="modal-header"> <h5 class="modal-title" id="changeModalLabel"> Change config value </h5> <button type="button" class="close" data-dismiss="modal" aria-label="Close" > <span aria-hidden="true">×</span> </button> </div> <div class="modal-body"> <form> <div class="form-group"> <label for="current-value" class="col-form-label" >Current value:</label > <input type="text" class="form-control" id="current-value" /> </div> <div class="form-group"> <label for="new-value" class="col-form-label">New value:</label> <textarea class="form-control" id="new-value"></textarea> </div> </form> </div> <div class="modal-footer"> <button type="button" class="btn btn-secondary" data-dismiss="modal" > Close </button> <button type="button" id="btnUpdate" class="btn btn-primary"> Update </button> </div> </div> </div> </div> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script> <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.7/umd/popper.min.js" integrity="sha384-UO2eT0CpHqdSJQ6hJty5KVphtPhzWj9WO1clHTMGa3JDZwrnQq4sF86dIHNDz0W1" crossorigin="anonymous" ></script> <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/js/bootstrap.min.js" integrity="sha384-JjSmVgyd0p3pXB1rRibZUAYoIIy6OrQ6VrjIEaFf/nJGzIxFDsf4x0xIM+B07jRM" crossorigin="anonymous" ></script> <script type="text/javascript"> $('#changeModal').on('show.bs.modal', function (event) { var button = $(event.relatedTarget); var configName = button.data('config'); var currVal = button.data('currval'); var modal = $(this); modal.find('.modal-title').text('Change value for ' + configName); modal.find('.modal-body input').val(currVal); }); $('#btnUpdate').click(function (event) { var element = $('input#current-value'); var modal = $(this); var url = '/fizzes/abc123/buzzes/abc235'; var configName = element.val(); var newVal = $('textarea#new-value').val(); console.log(newVal); $.ajax({ url: url, method: 'POST', data: { [configName]: newVal }, success: (data) => { console.info(data); }, error: (err) => { console.error(err); }, }); }); </script> </body> </html>Aparte, definitivamente puede ignorar el hecho de que estoy usando $ .ajax en lugar de la publicación que usó, eso fue solo un control de cordura para mí.