Render list action in modal sonata admin - twig

I try to render the list action of my admin class in sonata in a modal, but I can't find the right way to do it?
Someone can help me please?
I just want the datagrid and not all the page(menu, topbar,etc...).
Actually i doing this like that :
En Cours modal
<div class="modal fade" id="basicModal1" tabindex="-1" role="dialog" aria-labelledby="basicModal" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>
<h4 class="modal-title" id="myModalLabel">Modal title</h4>
</div>
<div class="modal-body">
{{render (controller('MonBundle:Controller:list',{'id':object.id}))}}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
But I've got this error with the render :
Error: Call to a member function getRelativePath() on null

Whole page is shown because you are including a template of the standard controller action. Sonata use conditions for app.request.isXmlHttpRequest to detect if the view is opened in modal (via AJAX) or in a standard way.
So you may solve your problem by these steps:
1) Bind JS function (which opens modal) on button click.
2) When button clicked, load URL and paste its response body into .modal-body
URL: {{ path('your-list-action-name', {'id': object.id}) }}
It will solve the problem when you add a new record to the list from your page but list will show old records (because in your snippet, list renders once, on modal first render).
Additional info could be found in Sonata's ORM Admin Bundle (if you use ORM) under Resources/views/CRUD/edit_orm_many_association_script.html.twig

Related

EJS just outputs the first found user in some cases

I'm Using mongoDB and ejs to display all my users in a table. The table also has some action buttons to delete the user and to change the users role. The buttons open a popup to change the role or to confirm the deletion. But EJS doesn't pass the users info into the popup. It works totally fine in the table, but not in the popup.
My EJS User Table with the Role change Popup:
<tbody>
<%users.forEach(function(users){%>
<tr>
<td><%=users.name%></td>
<td><%=users.username%></td>
<td><%=users.createdAt%></td>
<td><span class="badge label-table badge-<%=users.role%>"><%=users.role%></span></td>
<td><span class="badge label-table badge-<%=users.verifyEmailToken%>"><%=users.verifyEmailToken%></span></td>
<td>
<button type="submit" class="btn btn-xs btn-success" data-toggle="modal" data-target="#con-close-modal" name="changeRoleButton"><i class="remixicon-user-settings-line"></i></button>
</td>
</tr>
<div id="con-close-modal" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true" style="display: none;">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Change <%=users.name%> Role</h4>
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
</div>
<form class="" action="/changeuserrole" method="post">
<div class="modal-body p-4">
<div class="row">
<div class="col-md-12">
<div class="form-group">
<label for="field-1" class="control-label">User Role</label>
<select class="form-control" name="role">
<option>Partner</option>
<option>Admin</option>
<option>User</option>
</select>
</div>
<button type="submit" value="<%=users._id%>" name="userroleid" class="btn btn-primary">Submit</button>
</div>
</div>
</div>
</form>
</div>
</div>
</div>
<%});%>
</tbody>
Here is my app.js where I search for the users and pass them to EJS:
app.get("/users", function(req, res) {
if (req.isAuthenticated() && req.user.role === "Admin") {
User.find({}, function(err, foundUsers) {
if (err) {
console.log(err);
} else {
res.render("users", {
users: foundUsers,
name: req.user.name.replace(/ .*/, ''),
email: req.user.username,
});
}
});
} else {
res.redirect("/login");
}
});
All the <%=users...%> tags work inside the table, but not inside the popup divs. Inside the Popup it just displays the information from the first user in the Database, which is super strange.
I would be very thankful for any kind of help. Thanks!
Your ejs code is good. I think that the problem is the id of each modal.
For each user you generate a modal with id="con-close-modal", So all your modals have the same id. As a result, every submit button (all of them have the same data-target="#con-close-modal"), triggers the same modal, probably the first one.
I recommend you, give each modal a unique id like
<div id="<%= users._id %>" class="modal fade" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true" style="display: none;">
and give each submit button the right data-target attribute
<button type="submit" ... data-target="#<%= users._id %>"...></button>
I may be wrong, but since the popup is displaying only the info from the first user, you may need the specific user id to be apart of the link. I had a similar issue with a project, except it was a link to a new view instead of a pop up.
I hope this documentation may be of some help
https://mongodb.github.io/node-mongodb-native/api-bson-generated/objectid.html

Send value from one button to another button express-handlebars?

I am showing some dynamic value on a table. in the table each row have a delete button( Suppose Button A ). If click the delete button ( Button A ) open a modal to confirm delete and there have confirm button( Button B ). From confirm button I am calling the api to delete the entity with the entity id.
Now I have the id on Button A and I am sending the request from button B. How can I sent the id from Button A to Button B.
Button A:
<td>
<button data-toggle="modal" value = {{this.id}} data-target="#myModal">
<i class="fa fa-trash-o" aria-hidden="true"></i>
</button>
</td>
Modal With button B:
<div class="modal fade" id="myModal" role="dialog">
<div class="modal-dialog">
<!-- Modal content-->
<div class="modal-content">
<div class="modal-header">
<h4 class="modal-title">Confirm Delete</h4>
<button type="button" class="close" data-dismiss="modal">×</button>
</div>
<div class="modal-header">
Are you sure you want to delete the entry?
</div>
<div class="modal-footer">
yes
</div>
</div>
</div>
</div>
I have given the {{this.id}} on the url of button B but it is always deleting the top or last element ?
add a class (example .delete) to the button,
<button data-toggle="modal" value ={{this.id}} class="delete" data-target="#myModal">
<i class="fa fa-trash-o" aria-hidden="true">delete</i>
</button>
then add a class to the confirmation link (example .yes):
yes
then get onclick event on the button and get the value of the button and insert it in the href attribut :
$(document).on("click", ".delete", function () {
var value = $(this).val();
console.log("value : ", $(this).val())
$(".modal-dialog .yes").attr("href","/admin/dashbord/category/"+value+"/delete");
});
see this codepen

nodejs delete route warning/confirmation

I'm building a website with nodejs, express and mongoose. I have concerts to be added in using the RESTful routes and comments of users that are connected with those comments.
When I come to the DELETE route, I want the user to be warned instead of deleting a comment directly. Therefore I'm using bootstraps modal.
Anyhow, this worked just fine for tourdates itself, but on the comments that are connected to the tourdates, I get a very strange behaviour on this. Instead of deleting the selected comment, it always deletes the oldest comment. But this is ONLY if I put the bootstraps modal in, without the modal it deletes the right one, even though I don't change anything on the delete form.
Here's the ejs form without the modal (deletes the chosen comment):
<form action="/tourdates/td/<%=concert._id%>/comments/<%=comment._id%>?_method=DELETE" method="POST" class="deleteForm">
<input type="submit" class="btn btn-danger btn-sm" value="Delete">
</form>
That's the same code with the modal (delete's always the oldest comment instead of the chosen one):
<form action="/tourdates/td/<%=concert._id%>/comments/<%=comment._id%>?_method=DELETE" method="POST" class="deleteForm">
<a class="btn btn-danger btn-sm" data-toggle="modal" href="#collapseDelete" role="button" data-target="#deleteConcertComment">Delete</a>
<div class="modal fade" id="deleteConcertComment" tabindex="-1" role="dialog" aria-labelledby="exampleModalCenterTitle" aria-hidden="true">
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalCenterTitle">Delete Komment?</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
Are you sure?
</div>
<div class="modal-footer">
<button class="btn btn-secondary btn-sm" data-dismiss="modal">Cancel</button>
<input type="submit" class="btn btn-danger btn-sm" value="Delete">
</div>
</div>
</div>
</div>
</form>
And here's my route:
router.delete("/tourdates/td/:id/comments/:comment_id", function(req, res) {
Comment.findByIdAndRemove(req.params.comment_id, function(err) {
if(err) {
req.flash("error", "Es ist ein Fehler aufgetreten!");
console.log(err);
} else {
req.flash("success", "Kommentar wurde gelöscht!");
res.redirect("/tourdates/td/" + req.params.id);
}
});
});
I really can't see why the second version deletes the oldest comment in the database instead of the chosen one. And as I said, I have exactly the same thing for the tourdates itself using the route /tourdates/td/:id and there it works just fine.
Any ideas?
Update:
#Neil you're right. My mistake was, that I inspected the delete buttons that I "slotted ahead" before the actual delete button. Since I want this "Are you sure" function, the delete buttons that stick to the single comments won't fire the post request, they shall be fired by the delete-button inside the modal.
Now, if I inspect the delete buttons that are slotted ahead, I see three different forms (one after another) in my inspections view and all of them would trigger different comment id's. But if I click on them, the modal will open and the delete button inside the modal always points to the same id.
Please see the picture, the modal-delete button always points to the same form whilst the single delete-buttons point to different forms. But what do I have to change on my code then? enter image description here

Pass Data from MongoDB to Bootstrap Modal Using EJS

I'm building an express app which comprises ejs and bootstrap for rendering views, node and express for server side and mongodb for storage.
I have a form (contained in a modal) in which I can post data. After submitting the form, the values are saved to mongodb.
Here's the snippet for edit:
<td><%= cats.image %></td>
<td><a type="button" data-toggle="modal" data-target="#editCategory" href="#">Edit</a>
// without using the modal above, I'll have to create a new page to edit only one item
// I think it's a waste of page space and bad UX, so I am going with the modal
<!--<a href="/admin/categories/edit-category/<%= cats._id %>">--> // I want to get the values from this id and show in the modal
<!--<button type="button" class="btn btn-primary btn-sm">Edit</button>-->
<!--</a>-->
</td>
When I click on the edit button, I want to get the id of the item and retrieve it's values to display in the modal.
Here's the full modal view:
<!-- Edit Category Modal -->
<div class="modal fade" id="editCategory" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
<div class="modal-dialog" role="document">
<div class="modal-content">
<form action="/admin/categories/edit-cateory/<%= %>" method="post" enctype="multipart/form-data">
<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" id="myEditCategoryLabel">Edit Category</h4>
</div>
<div class="modal-body">
<div class="form-group">
<label>Title</label>
// this value should come from the category id but don't know how to pass it
<input value="<%= %>" name="title" class="form-control" type="text" placeholder="Category Title"> <br>
<label>Upload Image</label>
<input class="form-control selImg" type="file" accept="image/*" onchange="showImage.call(this)">
<img src="#" class="imgPreview" style="display: none; height: 100px; width: 100px">
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
<button type="submit" class="btn btn-primary">Save Edits</button>
</div>
</form>
</div>
</div>
</div>
How can I pass the data from mongodb to the modal using ejs?
Any help will be much appreciated.
Store your ID somewhere: hidden inputs or data-attributes.
<tr data-id="<%= cats.id %>">
<td><%= cats.image %></td>
<td>
<a type="button" class="edit" href="#">Edit</a>
</td>
</tr>
Then, create an onclick event handler such that, upon clicking on the button,
it will fetch the extra data via AJAX and open the modal dynamically after you get a response.
$('a.edit').click(function (e) {
e.preventDefault();
var tr = $(this).closest('tr'),
modal = $('#editCategory');
// make AJAX call passing the ID
$.getJSON('/admin/categories/get-cateory/' + tr.data('id'), function (data) {
// set values in modal
modal.find('form').attr('action', '/admin/categories/get-cateory/' + tr.data('id') );
modal.find('[name=title]').val( data.title );
// open modal
modal.modal('show');
});
});
You will need to create a route for fetching a single object (I'll leave that to you)
app.get('/admin/categories/get-cateory/:id', function (req, res) {
// TODO: fetch data using passed ID
// once you have the data, simply send the JSON back
res.json(data);
});

nested template rendering in backbone.js

I have a template like
script type: "text/template", id: "list-template", '''
<div class="display">
<div id="list-name"><%= name %></div>
<span class="list-destroy"></span>
</div>
<div>
<ul id="ul-cards">
</ul>
</div>
<div class="edit">
<input class="list-input" type="text" value="<%= name %>" />
<input id="btnEdit" type="button" value="Save" class="primary wide js-add-list" />
<input id="hdnListId" type="hidden" value="<%= listId%>" />
</div>
<form class="add-list-card js-add-list-card clearfix">
<textarea placeholder="Add card" class="new-card"></textarea>
<input type="button" value="Add" class="primary js-add-card">
<a class="app-icon close-icon dark-hover cancel js-cancel-add-card" href="#" id="closeCard"></a>
</form>
'''
in this template i have <ul id="ul-cards"> element in which i want to render another template which display list inside this ul.
this template is :
script type: "text/template", id: "card-template", '''
<div>
<span class="card-name"><%= name %></span>
</div>
'''
is it possible or i have to do it in another way?
please help me if anyone have idea.
thanks in advace.
it is worked but still i have one problem in data display in
<ul id="ul-cards"> there sholud be 2 as per records in my database but it will display only 1 . data fetch properly but display only last data.
There are two ways to do this: the DOM way and the template way.
The DOM way involves adding your views using DOM methods: you have your ListView and your CardView; the ListView invokes individual CardViews that fill in the ListView's element.
The template way requires that you remember this: backbone's views are policy frameworks, not policy templates. Render doesn't have to render into the DOM. You can use render() to return a string, for example. If your event manager is on the ListView object only (possible; I've done this), then you can have ListView invoke "the resulting array of an array of CardView renders" and insert that directly into ListView's template. This is actually faster, as you only require the browser to analyze the entire ListView HTML blob once, when it's inserted into the innerHTML of the parent DOM object.

Resources