How to load specific div or id ajax and laravel - javascript

i have a comment system on my app in laravel and i can edit my comments with ajax but once edited it doesn't load automatically the edited comment. To see the edited comment i need to reload the page manually. I will put some of the code here.
This is the JS:
var commentId = 0;
var divcomment = null;
$('.edit-comment').click(function(event){
event.preventDefault();
/* Accedemos al Div Que contiene el Panel*/
var divcomment = this.parentNode.parentNode;
/* Buscamos el Contenido con Id display-text */
commentId = $("#comment-post", event.target.parentNode.parentNode).data('commentid');
var commentBody = $(divcomment).find('#display-comment').text();
$('#comment').val(commentBody);
$('#edit-comment').modal();
/* Asignas a tu modal */
});
$('#modal-save').on('click', function(){
$.ajax({
method: 'PUT',
url: urlEdit,
data: {
comment: $('#comment').val(),
commentId: commentId,
_token: token,
_method: 'PUT',
dataType: 'json',
}
})
.done(function (msg){
$(divcomment).text(msg['new_comment']);
$('#edit-comment').modal('hide');
});
});
This is the Html:
<article class="row">
<div class="col-md-3 col-sm-3 hidden-xs">
<figure class="thumbnail">
<img class="img-responsive" src="/uploads/avatars/{{ $comment->user->profilepic }}" />
<figcaption class="text-center">{{ $comment->user->name }}</figcaption>
</figure>
</div>
<div class="col-md-8 col-sm-8">
<div class="panel panel-default arrow left">
<div class="panel-body">
<header class="text-left">
<div class="comment-user"><i class="fa fa-user"></i> {{ $comment->user->name }}</div>
<time class="comment-date" datetime="{{ $comment->created_at->diffForHumans() }}"><i class="fa fa-clock-o"></i> {{ $comment->created_at->diffForHumans() }}</time>
</header>
<div id="comment-post" data-commentid="{{ $comment->id }}">
<p id="display-comment">{{ $comment->comment }}</p>
</div>
</div>
<div class="panel-footer list-inline comment-footer">
#if(Auth::guest())
No puedes responder ningún comentario si no has ingresado.
#else
#if(Auth::user() == $comment->user)
Editar Eliminar
#endif
#if(Auth::user() != $comment->user)
Responder
#endif
#endif
</div>
</div>
</div>
</article>
2 variables created on the view
var token = '{{ Session::token() }}';
var urlEdit = '{{ url('comments/update') }}';
and finally the modal where i edit the comment:
<div class="modal fade" id="edit-comment" tabindex="-1" role="dialog">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" style="color:#000;">Editar Comentario</h4>
</div>
<div class="modal-body">
<form>
<div class="form-group">
<label for="comment">Editar comentario</label>
<textarea class="form-control" name="comment" id="comment"></textarea>
</div>
</form>
</div>
<div class="modal-footer">
<button type="button" class="btn-comment-dismiss btn-comment-modal" data-dismiss="modal"><span class="glyphicon glyphicon-remove"></span> Cerrar</button>
<button type="button" class="btn-comment-edit btn-comment-modal" id="modal-save"><span class="glyphicon glyphicon-ok"></span> Editar</button>
</div>
</div>
</div>
</div>
Everything's working but the only thing i need is to load the edited comment back without refresh the whole page, btw i used $('#display-comment').load(document.URL + ' #display-comment'); and with this line i succesfully load the edited comment but, it load all the comments on the edited one, so i have to refresh the whole page to show just the edited.

Assuming that the data sent to the php side of things is the same data that you then want to update to, the following should work:
$('#modal-save').on('click', function(){
var comment = $('#comment').val();
// shove the edited comment into a variable local to the modal handler
$.ajax({
method: 'PUT',
url: urlEdit,
data: {
comment: comment, // reference said variable for ajax data
commentId: commentId,
_token: token,
_method: 'PUT'
},
dataType: 'json'
})
.done(function (msg){
//$(divcomment).text(msg['new_comment']);
// I commented out the above line as it clears the
// divcomment div's text entirely.
// Comment out the below 'if check' if it is not needed.
if (msg.success === true) {
$(divcomment).find('#display-comment').text(comment);
// And overwrite the #display-comment div with the new
// data if the user was successful in editing the comment
}
$('#edit-comment').modal('hide');
});
});
In a previous question of yours, you had a controller method on the php side of things that handled the ajax. Instead of redirecting(since it is ajax, there is no redirect), you should instead return json to indicate whether the action was successful or not. Here is an example of that:
public function update(Request $request)
{
//...
$comment = Comment::find($request['commentId']);
if (Auth::user() != $comment->user) {
return response()->json(['success' => false], 200);
}
//...
return response()->json(['new_comment' => $comment->comment, 'success' => true], 200);
}
I referenced the above json in my answer on the javascript side of things; if you are not going to use the json response, then simply comment out the line(as I also noted in the code).
Update:
I missed something in your earlier block of code; you declare divcomment outside of the edit link's handler, but then you re-declare it inside of that handler again. I missed this in my earlier answer, so simply deleting the var from it, so it uses the outside declaration, fixes your code:
var commentId = 0;
var divcomment = null; //this is already declared, no reason to declare it
// again
$('.edit-comment').click(function(event){
event.preventDefault();
/* Accedemos al Div Que contiene el Panel*/
divcomment = this.parentNode.parentNode;
// ^ remove the var, making this use the global variable you already
// made above
/* Buscamos el Contenido con Id display-text */
commentId = $("#comment-post", event.target.parentNode.parentNode).data('commentid');
var commentBody = $(divcomment).find('#display-comment').text();
$('#comment').val(commentBody);
$('#edit-comment').modal();
/* Asignas a tu modal */
});

Related

Is there a possibility to bind the Form to a modal bootstrap window without using the load call?

I'm using ajax to make a request and open a modal bootstrap window afterwards. The problem is that when I use ajax, I make a request to my controller, and the return (modal content) I load as follows:
//modal loading
$('#contentModalFinanceiroParcela').html(data);
//exibição da modal
$('#modalFinanceiroParcela').modal({
keyboard: true,
}, 'show');
So far, everything perfect. The problem is that from then on, I can't bind the form to register the submit event of the form. In the function bindFormFinanceiroParcela, no matter how much I pass the "dialog", bind does not work.
bindFormFinanceiroParcela(document.getElementById("contentModalFinanceiroParcela"));
Searching the forums, I found that the process works if I load the modal using the "load" command, as below, but I can't do it like that, otherwise it will make a second request to the controller, because previously, I already used ajax .
//That way it works, but I can't use it.
$('#contentModalFinanceiroParcela').load(url, function () {
$('#modalFinanceiroParcela').modal({
keyboard: true
}, 'show');
// Inscreve o evento submit
bindFormFinanceiroParcela(this);
stopLoadPage();
});
Is there a possibility that I can bind the form without using the "load" command mentioned in the script above?
function openModalFinanceiroParcelaSemURL(data) {
startLoadPage();
//Create the modal window block in the body of the page
if (!$("#modalFinanceiroParcela").data('bs.modal'))
CreateModalFinanceiroParcela();
//Load modal content via ajax request
$('#contentModalFinanceiroParcela').html(data);
$('#modalFinanceiroParcela').modal({
keyboard: true,
}, 'show');
bindFormFinanceiroParcela(document.getElementById("contentModalFinanceiroParcela"));
stopLoadPage();
}
function bindFormFinanceiroParcela(dialog) {
$('form', dialog).submit(function (e, i) {
if ($(this).valid() || i) {
startLoadOneMoment();
$.ajax({
url: this.action,
type: this.method,
data: $(this).serialize(),
success: function (result) {
if (result.success) {
window.location = window.location;
} else {
$('#contentModalFinanceiroParcela').html(result);
bindFormFinanceiroParcela();
}
stopLoadOneMoment();
}
});
return false;
} else {
return false;
}
});
function CreateModalFinanceiroParcela() {
var html = '<div class="modal modal-primary modal-system" tabindex="-1" role="dialog" id="modalFinanceiroParcela" data-backdrop="static"><div class="modal-dialog modal-dialog-centered"><div class="modal-content"><div class="content-modal-system" id="contentModalFinanceiroParcela"></div></div></div></div>';
$("body").append(html);
}
RAZOR DELETE:
#using Retaguarda.Domain.Enuns
#model Retaguarda.Application.ViewModels.Financeiro.FinanceiroParcela.FinanceiroParcelaViewModel
#{
ViewData["Title"] = "Excluir Parcela";
Layout = null;
}
<div>
<form asp-action="Delete" id="frm-excluir-financeiro-parcela">
#Html.AntiForgeryToken()
<div class="modal-shadow">
<div class="modal-header modal-header-primary">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
<h4><i class="modal-title text-center glyphicon glyphicon-trash"></i> #ViewData["Title"] </h4>
</div>
<div class="panel">
<div class="panel-body container-fluid pt-15 pl-15 pr-15">
<div class="form-horizontal">
<vc:summary />
<br />
<div class="message-delete">
#Html.HiddenFor(model => model.Id, new { id = "hid-financeiro-parcela-id" })
<i class="icon fa-trash" aria-hidden="true"></i>
<p>
Tem certeza de que deseja excluir a parcela #(Model.Parcela)?<br />
</p>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<div class="col-md-offset-2 col-md-10">
<div class="float-right">
<div class="btn-group btn-group-sm mr-auto"
role="group">
<div class="btn-group btn-group-sm" role="group">
#*<button id="btn-excluir-financeiro-parcela" type="submit" class="btn btn-success"><i class="icon wb-check"></i> Excluir </button>*#
<button id="btn-excluir-financeiro-parcela" type="button" class="btn btn-success"><i class="icon wb-check"></i> Excluir </button>
<button id="btn-cancelar-financeiro-parcela" class="btn btn-danger" data-dismiss="modal"><i class="icon wb-close"></i> Cancelar </button>
</div>
</div>
</div>
</div>
</div>
</div>
</form>
</div>
<script src="~/lib/jquery-validation/dist/jquery.validate.js"></script>
<script src="~/lib/jquery-validation-unobtrusive/jquery.validate.unobtrusive.js"></script>
#section Scripts {
#{await Html.RenderPartialAsync("_ValidationScriptsPartial");}
}
Ajax call
$('#dtFinanceiroParcela').on('click', 'tr .btn-excluir-financeiro-parcela', function (e) {
e.preventDefault();
startLoadOneMoment();
var id = $(this).attr('data-id');
var data = { id: id };
var dataURL = jQuery.param(data);
$.ajax({
url: "/financeiro-parcela-gerenciar/remover-financeiro-parcela/" + id,
type: "GET",
// data: dataURL,
contentType: "application/json",
async: false,
success: function (result) {
if (typeof result.success !== 'undefined') {
if (!result.success) {
stopLoadOneMoment();
swal("Oops", result.message, "error");
return false;
}
}
// alert(this.url);
stopLoadOneMoment();
openModalFinanceiroParcelaSemURL(result);
return false;
},
error: function () {
stopLoadOneMoment();
alert("Oops! Algo deu errado.");
return false;
}
});
Your form inside razor does not contain any submit button because its commented out.
#*<button id="btn-excluir-financeiro-parcela" type="submit" class="btn btn-success"><i class="icon wb-check"></i> Excluir </button>*#
Remove the comment or change the type of the other button to "submit"
I guess the submit event is attached successfully but never called due to the missing submit button inside your form.

Jquery strange chaining of Ajax requests

I have a div called project and it is rendered with EJS
There several projects in the data for EJS, they are rendered by forEach loop - so several similar div appear.
The project div has id for identification in Jquery.
Further it has a project.name and project.id as a data-*
The problem which I encountered:
If I don't reload the page as intended - first try works well and Element inner text get updated correctly.
But on second try to change another project name both are changed to value of previous, so to say for both projects. In few words - new change overrides all previous. How is it possible?
Link to see how it looks in GIF
Imgur
Strange behaviour of chaining requests Imgur
<%userData.forEach(function(project){%>
<div class="project" id='project <%=project.id%>'>
<div class="projectHeader">
<div class="projectTitle">
<h5 id="projectTitle <%=project.id%>" class="projectName">
<%=project.name%>
</h5>
<div class="projectButtons">
<span data-toggle="tooltip" data-placement="top" title="Edit Project Title">
<a data-toggle="modal" data-target="#editProjectTitleModal">
<i id="editProjectName" class="editProject fas fa-pencil-alt"
data-name="<%=project.name%>" data-id="<%=project.id%>"></i>
</a>
</span>
</div>
</div>
</div>
A simple modal is called when the a tag in project is clicked.
<div class="modal fade" id="editProjectTitleModal" tabindex="-1" aria-labelledby="exampleformModal" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<form class="" action="" method="">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Edit Title</h5>
</div>
<div class="modal-body">
<div class="input-group">
<input id="editProjectNameInput" autocomplete="off" pattern="[a-zA-Z0-9 ].{1,25}" title="1 to 25 characters" class="form-control" aria-label="With textarea" placeholder="Enter new title" required></input>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="submit" id="confirmEditProjectName" class="btn btn-primary">Save changes</button>
</div>
</form>
</div>
</div>
</div>
Jquery event handler which serves to change project.name, at first sends it to database and ammend DOM with new name. So the database get the new data, but the page is not reloaded and project.name changed simultaneously.
It grabs project-name and project-id and sends Ajax regular post - method, on success - change element's inner text to project-name
// Edit Project Title by ID
$(document).on('click', "#editProjectName", function() {
//Grab Id of the Project
var editProjectId = $(this).attr('data-id');
//Fill Modal input with current project.name
var currentTitle = document.getElementById('projectTitle ' + editProjectId).innerText;
$("#editProjectNameInput").val(currentTitle)
var url = '/editProjectName';
$('#confirmEditProjectName').on('click', function(event) {
//Take new project name from updated modal input
var newTitle = $("#editProjectNameInput").val();
//If they are same - alert
if (currentTitle === newTitle) {
event.preventDefault();
alert("New Title should be different")
} else {
event.preventDefault();
if (newTitle.length > 1 && newTitle.length <= 25) {
$.ajax({
type: "POST",
url: url,
data: {
projectName: newTitle,
projectID: editProjectId
},
success: function(result) {
//Hide modal and change element inner text to new value
$("#editProjectTitleModal").modal('hide')
document.getElementById('projectTitle ' + editProjectId).innerText = newTitle;
},
error: function(err) {
console.log(err);
}
})
}
}
})
})
I removed the space from the IDs and I changed from using the ID of #editProjectName to just using the class that is already on that object of editProject.
<%userData.forEach(function(project){%>
<div class="project" id='project<%=project.id%>'>
<div class="projectHeader">
<div class="projectTitle">
<h5 id="projectTitle<%=project.id%>" class="projectName">
<%=project.name%>
</h5>
<div class="projectButtons">
<span data-toggle="tooltip" data-placement="top" title="Edit Project Title">
<a data-toggle="modal" data-target="#editProjectTitleModal">
<i class="editProject fas fa-pencil-alt"
data-name="<%=project.name%>" data-id="<%=project.id%>"></i>
</a>
</span>
</div>
</div>
</div>
// Edit Project Title by ID
$(document).on('click', ".editProject", function() {
//Grab Id of the Project
var editProjectId = $(this).attr('data-id');
//Fill Modal input with current project.name
var currentTitle = document.getElementById('projectTitle' + editProjectId).innerText;
$("#editProjectNameInput").val(currentTitle)
var url = '/editProjectName';
$('#confirmEditProjectName').on('click', function(event) {
//Take new project name from updated modal input
var newTitle = $("#editProjectNameInput").val();
//If they are same - alert
if (currentTitle === newTitle) {
event.preventDefault();
alert("New Title should be different")
} else {
event.preventDefault();
if (newTitle.length > 1 && newTitle.length <= 25) {
$.ajax({
type: "POST",
url: url,
data: {
projectName: newTitle,
projectID: editProjectId
},
success: function(result) {
//Hide modal and change element inner text to new value
$("#editProjectTitleModal").modal('hide')
document.getElementById('projectTitle' + editProjectId).innerText = newTitle;
},
error: function(err) {
console.log(err);
}
})
}
}
})
})
After some research I have found out that once the on('click') is called it is On until the page get reloaded.
Thanks to this Question and Answer:
https://stackoverflow.com/a/6121501/13541013
I figured out - on('click') event should be switched off by calling $(this).off() (this is the event)
In my case I had to make $(this).off() right after:
$(document).on('click', "#editProjectName", function() {
$(this).off() ... further code
And it has to be done for every single on('click') event in the script.

Symfony: A Button to query the database and popup

I need to create a button that will automatically search in my database all user with a "secouriste" Attribute set and print their firstname, lastname and phone number in a popup.
Here is what I found from my research:
In my HTML, I have to set a button which will enable a popup modal with id of the user I want to get and under this button, there is the code of my popup modal with a listener.
In my JS, I get the data (which is an object).
In Ajax, I need to pass the ID to my controller.
In PHP, I get the ID with a symfony request and FindOneBy.
But there are different problems with this technique: I dont need to get only one person but a list of person with the good attribute so maybe I should use "FindBy" instead of "FindOneBy", but someone said to me that I should use a custom FindAll(). I'm completely lost right now. Here is what I could gather from posts, I know that's far from right, but this is what I have.
//=============================================
// Recherche PopUp Secouriste
//=============================================
$(document).on('show.bs.modal', '#secouristeModal', function (e) {
var id = $('#secouristeModal').data('id');
$.ajax({
url: 'UserBundle/utilisateur',
method: 'POST',
data: {
id: id
}
}).done(function (data) {
// Si status est égal à true
if(data.status) {
console.log(data);
$('#userTitle').replaceWith(data.user.firstName);
}
}).fail(function (data) {
// Code if error
});
})
PHP
$user = $this->findBy($request->request->get('secouristeAttribute' -> $secouristeAttribute));
if($user) {
return new JSONResponse(array(
'user' => $user
));
} else {
// Faire code de retour avec une erreur (status = false)
}
}
<!-- Button trigger modal -->
<button type="button" class="btn btn-primary" data-toggle="modal" data-target="#secouristeModal">
Liste des secouristes
</button>
<!-- Modal des secouristes-->
<div class="modal fade" id="secouristeModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Liste des Secouristes</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<!-- prints a list but doesnt load it from db on request only -->
{% for user in workFlow.listeSecouriste|default('')%}
{% if user.tel is not null %}
<br />{{ user.username }} - {{ user.nom }} {{ user.prenom }} - {{ user.tel }}
{% else %}
<br />{{ user.username }} - {{ user.nom }} {{ user.prenom }}
{% endif %}
{% endfor %}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
Thank you very much for your help.
Exx
I don't think you can filter your query with a findAll so findBy is good.
But you need to pass an array, something like that:
$users = $this->findBy(['attribute' => $request->request->get('secouristeAttribute')]);
Also, I'm not really sure about that, but before you return your list of Users you could have to implement JsonSerializable Interface with the method jsonSerialize() (or at least the toArray() magic method).
I finally solved my problem, here is how I did it if it can help someone later:
//For my popup
function myAlert(message,titre='Information',btn='',class_msg='',fonction,args) {
//=======================================================
if (btn==''){
btn='<a name="btnOk" class="btn btn-success">Ok</a>';
}
if (class_msg!='') {
message='<div class="'+class_msg+'">'+message+'</div>';
}
myConfirm(message,titre,btn,fonction,args); // Message d'alerte
}
//listeSecouriste.html.twig
<ul>{% for secouriste in listeSecouriste |sort secouriste.nom %}
<li>{{ secouriste.fullName }} {{ secouriste.tel }}</li>
{% endfor %}
</ul>
//php: my controller
public function getSecours($agence=null){
$listeSecouriste = $this->getDoctrine()->getManager()->getRepository('SIGUserBundle:Utilisateur')->ListeSecouriste($agence);
$retour=array('ok'=>false);
if ($listeSecouriste!== null){
$retour['ok']=true;
$retour['html']=$this->renderView('SIGUserBundle:Utilisateur:listeSecouriste.html.twig',
array(
'listeSecouriste'=>$listeSecouriste
)
);
}
return new JsonResponse($retour);
}

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>

Laravel 4 validation in bootstrap modal

I'm a newbie to Laravel 4, and I'm trying to get a form validation in bootstrap modal.
My modal have a form with a text input and a submit button, and I want that when the validation fails, the modal show me the error.
But the modal, after the validation and the page refresh, is closed.
Here is the code from the controller and the view:
Controller code:
public function postAvatar()
{
$avatar_rules = array(
'avatar_src' => 'url',
);
$validator = Validator::make(Input::all(), $avatar_rules);
$validator->setAttributeNames(User::$names_attr);
if ($validator->passes())
{
$avatar_src = (Input::get('avatar_src'))? Input::get('avatar_src') : URL::asset('assets/images/user/default-user-avatar.png');
$user = User::find(Auth::id());
$user->avatar_src = $avatar_src;
if ($user){
return Redirect::to('dashboard')->withSuccess("Success: avatar updated.");
}
return Redirect::to('dashboard')->withError("Error: an error has occurred.");
}
return Redirect::back()->withErrors($validator);
}
View code:
<!-- Modal -->
<div class="modal fade" id="avatarModal" tabindex="-1" role="dialog" aria-labelledby="avatarModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
<h4 class="modal-title" id="avatarModalLabel">Update avatar</h4>
</div>
<div class="modal-body">
<h4><span class="label label-info">Current avatar</span></h4>
<img class="img-circle img-responsive dashboard-avatar" src="{{ $user->avatar_src }}" alt="{{ $user->username }} avatar">
<div class="divider"></div>
<h4><span class="label label-info">New avatar</span></h4>
{{ Form::open(array('url' => 'dashboard/avatar', 'method'=>'post', 'role'=>'form')) }}
<ul>
#foreach($errors->all() as $error)
<div class="alert alert-danger" role="alert">{{ $error }}</div>
#endforeach
</ul>
<div class="form-group">
<label for="avatar_src" class="control-label">Link avatar</label>
<input type="text" name="avatar_src" class="form-control" id="avatar_src" placeholder="Link of avatar image url">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Update</button>
</div>
{{ Form::close() }}
</div>
</div>
</div>
How can I resolve ?
Thanks.
SOLVED:
Controller code:
public function postAvatar()
{
$avatar_rules = array(
'avatar_src' => 'url',
);
$validator = Validator::make(Input::all(), $avatar_rules);
$validator->setAttributeNames(User::$names_attr);
if ($validator->passes())
{
$avatar_src = (Input::has('avatar_src'))? Input::get('avatar_src') : URL::asset('assets/images/user/default-user-avatar.png');
$user = User::find(Auth::id());
$user->avatar_src = $avatar_src;
if ($user->save()){
if(Request::ajax()){
return Response::json(array('success' => true));
}
}
return Redirect::to('dashboard')->withError("Error: an error has occurred.");
}
return Response::json(array('errors' => $validator->errors()->toArray()));
}
View code:
<!-- Modal -->
<div class="modal fade" id="avatarModal" tabindex="-1" role="dialog" aria-labelledby="avatarModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
<h4 class="modal-title" id="avatarModalLabel">Update avatar</h4>
</div>
<div class="modal-body">
<h4><span class="label label-info">Current avatar</span></h4>
<img class="img-circle img-responsive dashboard-avatar" src="{{ $user->avatar_src }}" alt="{{ $user->username }} avatar">
<div class="divider"></div>
<h4><span class="label label-info">New avatar</span></h4>
{{ Form::open(array('url' => 'dashboard/avatar', 'id'=>'avatar_form', 'method'=>'post', 'role'=>'form')) }}
<div class="alert alert-danger avatar_alert" role="alert" style="display: none">
<ul></ul>
</div>
<ul>
</ul>
<div class="form-group">
<label for="avatar_src" class="control-label">Link avatar</label>
<input type="text" name="avatar_src" class="form-control s_tooltip" id="avatar_src" placeholder="Avatar image links">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Update</button>
</div>
{{ Form::close() }}
</div>
</div>
</div>
Ajax:
<script>
$(document).on('submit', '#avatar_form', function(event){
var info = $('.avatar_alert');
event.preventDefault();
var data = { avatar_src: $("#avatar_src").val() }
$.ajax({
url: "/dashboard/avatar",
type: "POST",
data: data,
}).done(function(response) {
info.hide().find('ul').empty();
if(response.errors)
{
$.each(response.errors, function(index, error){
info.find('ul').append(error);
});
info.slideDown();
}
else if(response.success){
window.location.href = "/dashboard";
}
});
});
</script>
Your best bet would be to validate the form via AJAX to avoid the page reloading entirely. You would then check the response of your AJAX request for the presence of errors and show them inside the modal if they exist.
You could also add in client side validation to prevent the request being made until the rules are satisfied. I wouldn't recommend using this INSTEAD of server side validation but using it ASWELL as is normally quite desirable.
To accomplish this, you'd need to do something along these lines:
Javascript:
Catch submit event of your form and make an AJAX request.
$(document).on('submit', 'form', function(event){
event.preventDefault();
var data = { avatar_src: $("#avatar_src").val(); };
$.ajax({
url: "/dashboard/avatar",
data: data
type: "POST",
}).done(function(response) {
if(response.errors)
{
// Add error to Modal Body
}
else
{
// Show success message, close modal?
}
});
});
Backend:
Modify your controller method to detect if the current request is an AJAX request and if so, return the response in JSON instead of Redirecting. For example:
if(Request::ajax())
{
return Response::json(array('errors' => $validator->messages()));
}
else
{
return Redirect::back()->withErrors($validator);
}
I've not tested any of that code so might contain some typos/errors but hopefully this helps you!
I was facing same issue. After research on internet,I found that Laravel don't support withSuccess('success_msg') method.
return Redirect::to('dashboard')->withSuccess("Success: avatar updated.");
Here is complete discussion on this topic:
https://github.com/laravel/framework/issues/906.
But you can handle this issue with this approach:-
- For Error message:-
[code has to be added in controller]
return Redirect::to('view')->withErrors('your error message.');
[code has to be added in view]
#if(isset($errors) && count($errors->all())>0)
<ul>
#foreach($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
#endif
- for succcess message:-
[code has to be added in controller]
$success_msg='your success message.';
Session::flash('successMsg', $success_msg);
return Redirect::to('view');
[code has to be added in view]
#if (Session::has('successMsg'))
{{ Session::get('successMsg') }}
#endif
This approach is working fine for me.
For better display of your errors you can use bootstrap css.

Categories