Reputation: 159
I want to display data from datatable to modal bootstrap.
Example:
Name | prenom | id |edit
example | test | 2 |button edit
Button will send data to modal to display for update.
Button code:
<a class="btn btn-info" role="button" data-toggle="modal" data-form="{% url 'up' id=val.id }" data-target="#myEdit" >Edit</a>
Modal code:
<div class="modal fade" id="myEdit" role="dialog">
<div class="modal-dialog">
<form class="well contact-form" method="post" action="{% url
'up'}">
{% csrf_token %}
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Modal Header</h4>
</div>
<div class="modal-body">
<label for="usr">Name:</label>
<input type="text" class="form-control" required="" name="uss" value="{{ instance.name }}" id="uss">
<label for="pwd">Password:</label>
<input type="password" class="form-control" required="" value="{{ instance.sname }}" name="pwd" id="pwd" >
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-default">Valider</button>
<button value="" type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</form>
</div>
</div>
views.py
def posts_edit(request, id=None):
instance = get_object_or_404(namemodel, id=id)
context={
'instance': instance
}
return render(request, '/ges/sortie/', context)
I want to display two values Name
and prenom
in modal, the data show it from database.
I think the best solution is using ajax.
Upvotes: 3
Views: 20791
Reputation: 6726
Your modal code contains a form
, but you are asking how to display some data, so it leaves me a bit confusing what you really want to do. Please be more clear.
I am going to suppose you want to show some data on a modal
, and that data should be retrieved from the server using AJAX.
There are several ways to do this. Let me explain you two general options:
In your initial template you just have an empty div
which you can update with HTML code.
Everytime you want show some data, you do an AJAX request which will return HTML code (in this case the modal
HTML code) and you just insert it on your div
.
In your initial template you may have a skeleton of your HTML code (in this case the modal
HTML skeleton), and through javascript you can update some values on it.
Everytime you want to show some data, you do an AJAX request which may return JSON data and using that information you update the values in the HTML skeleton.
Using the first one implies writing more code in the backend (the Django template in this case) while the latter encourages you to write more javascript code in the frontend.
As rendering the template on server side is quite slow and the transfered data is also larger (all the HTML code usually contains more bytes than raw JSON data), the former option may be a bit slower. Anyway I believe that for this simple case such difference is not relevant.
As I prefer to work on the backend rather than writing too much javascript, the following solution will be an implementation of a Server Processed HTML. Here it is (you were pretty close btw):
Your main template:
<table class="table">
<thead>
<tr>
<th>Name</th>
<th>Prenom</th>
<th>ID</th>
<th>Edit</th>
</tr>
</thead>
<tbody>
<tr>
<td>{{ val.name }}</td>
<td>{{ val.prenom }}</td>
<td>{{ val.id }}</td>
<td><a class="btn btn-info" class="open-modal" data-url="{% url 'up' id=val.id }">Edit</a></td>
</tr>
<tr>
...
</tr>
...
</tbody>
</table>
<!-- Here we create this empty div for inserting modal -->
<div id="modal-div"></div>
Javacript in the main template:
var modalDiv = $("#modal-div");
$(".open-modal").on("click", function() {
$.ajax({
url: $(this).attr("data-url"),
success: function(data) {
modalDiv.html(data);
$("#myEdit").modal();
}
});
});
The important things here are that we have our button and a jQuery event that is triggered when someone clicks on it. The triggered function do the AJAX call, sets the returned HTML in the modal-div
and finally opens the brand-new modal.
Your controller (Django view):
def posts_edit(request, id=None):
instance = get_object_or_404(namemodel, id=id)
context={
'instance': instance
}
return render(request, 'modal.html', context)
Your modal template modal.html
<div class="modal fade" id="myEdit" role="dialog">
<div class="modal-dialog">
<form class="well contact-form" method="post" action="{% url 'up'}">
{% csrf_token %}
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Modal Header</h4>
</div>
<div class="modal-body">
<label for="usr">Name:</label>
<input type="text" class="form-control" required="" name="uss" value="{{ instance.name }}" id="uss">
<label for="pwd">Password:</label>
<input type="password" class="form-control" required="" value="{{ instance.sname }}" name="pwd" id="pwd" >
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-default">Valider</button>
<button value="" type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</form>
</div>
</div>
Upvotes: 18
Reputation: 964
A good option is using the Vue.js framework to build components and fill your form dynamically.
I like very much Vue.js and I built an app to solve your problem.
I'll go step by step explaining what I did.
views.js
from django.shortcuts import render
def home(request):
users = [dict(id=1, first_name='Megan', last_name='Fox'),
dict(id=2, first_name='Chester', last_name='Bennington')]
if request.POST:
for user in users:
if user['id'] == int(request.POST.get('id')):
user['first_name'] = request.POST.get('firstName')
user['last_name'] = request.POST.get('lastName')
return render(request, 'index.html', {'users': users})
We are going to need that event bus to show the modal. The event bus is the component which will "transport" events from one component to another. So we can listen and emit events globally.
vue-bus.js
const EventBus = new Vue();
Object.defineProperties(Vue.prototype, {
$bus: {
get: function () {
return EventBus;
}
}
});
row
component with Vue to show your data.I changed your data to firstName
and lastName
to explain better.
This component renders your row with data and set up the edit button to emit the event showModal
passing the data from the row.
components/row.js
Vue.component('row', {
template: `
<tr>
<td>{{ firstName }}</td>
<td>{{ lastName }}</td>
<td>{{ id }}</td>
<td><button @click="showModal">Edit</button></td>
</tr>
`,
props: ['firstName', 'lastName', 'id'],
methods: {
showModal: function() {
this.$bus.$emit('showModal', this.firstName, this.lastName, this.id);
}
}
});
modal
component with BootstrapThis component uses a x-template
on index.html to render its contents. On this component all you need is a listener to the showModal
event, so when the modal opens, it will be populated with the row
content.
components/modal.js
Vue.component('modal', {
template: '#modal-template',
data: function () {
return {
firstName: '',
lastName: '',
id: 0
}
},
mounted: function () {
this.$bus.$on('showModal', function (firstName, lastName, id) {
this.firstName = firstName;
this.lastName = lastName;
this.id = id;
}.bind(this));
}
});
If you take a look at Vue.js docs you will see how it works. Basically, it will mount your application in the element with id #app
.
Here I'm just listening to the showModal
event, so when this event is emitted, the modal shows up.
app.js
new Vue({
el: '#app',
data: {
showModal: false
},
mounted: function () {
this.$bus.$on('showModal', function () {
this.showModal = true;
}.bind(this));
}
});
css/styles.css
table {
margin: 20px;
}
td {
padding: 10px;
border: 1px solid #ccc;
}
.modal-mask {
position: fixed;
z-index: 9998;
top: 0;
left: 0;
width: 100%;
height: 100%;
background-color: rgba(0, 0, 0, .5);
display: table;
transition: opacity .3s ease;
}
.modal-container {
transition: all .3s ease;
}
.modal-enter {
opacity: 0;
}
.modal-leave-active {
opacity: 0;
}
So, what I'm doing here is iterating over the users lists populating the rows with the user data.
The modal template is inside a x-template
as I said before. You need to do some changes on Bootstrap modal to make this work like adding the class show
and changing the data-dismiss
attribute to close the modal.
The data is populated from the listener on components/modal.js. The bind is made on :value
. See the v-bind
documentation on Vue website to understand better how it works.
index.html
{% load static %}
<html>
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<link rel="stylesheet" href="{% static 'css/styles.css' %}">
</head>
<body>
<div id="app">
<table>
{% for user in users %}
<tr is="row" first-name="{{ user.first_name }}" last-name="{{ user.last_name }}" :id="{{ user.id }}"></tr>
{% endfor %}
</table>
<modal v-show="showModal" @close="showModal = false"></modal>
</div>
<script src="http://code.jquery.com/jquery-3.2.1.min.js" integrity="sha256-hwg4gsxgFZhOsEEamdOYGBf13FyQuiTwlAQgxVSNgt4=" crossorigin="anonymous"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<script src="//unpkg.com/vue"></script>
<script type="text/x-template" id="modal-template">
<transition name="modal">
<div class="modal-mask">
<div class="modal-container">
<div id="myModal" class="modal show" role="dialog">
<div class="modal-dialog">
<form method="post" action=".">
{% csrf_token %}
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" @click="$emit('close')">×</button>
<h4 class="modal-title">Edit User</h4>
</div>
<div class="modal-body">
<label for="name">First Name:</label>
<input type="text" class="form-control" name="firstName" :value="firstName" />
<label for="lastName">Last Name:</label>
<input type="text" class="form-control" name="lastName" :value="lastName" />
<input type="hidden" name="id" :value="id" />
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary">Save</button>
<button type="button" class="btn btn-default" @click="$emit('close')">Close</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</transition>
</script>
<script type="text/javascript" src="{% static 'vue-bus.js' %}"></script>
<script type="text/javascript" src="{% static 'components/row.js' %}"></script>
<script type="text/javascript" src="{% static 'components/modal.js' %}"></script>
<script type="text/javascript" src="{% static 'app.js' %}"></script>
</body>
</html>
When we click on Edit
:
Then we edit the data:
And save:
Upvotes: 0