2
2
3
3
{% block content %}
4
4
< div id ="author-books ">
5
- < h1 >
6
- Nested formset
7
- </ h1 >
8
- < div >
5
+ < div class ="jumbotron ">
6
+ < h1 > Django formsets with Vuejs</ h1 >
7
+ </ div >
8
+ < div class ="container ">
9
+ {% for message in messages %}
10
+ < div class ="alert {{ message.tags }} alert-dismissible " role ="alert ">
11
+ < button type ="button " class ="close " data-dismiss ="alert " aria-label ="Close ">
12
+ < span aria-hidden ="true "> ×</ span >
13
+ </ button >
14
+ {{ message }}
15
+ </ div >
16
+ {% endfor %}
9
17
< form enctype ="multipart/form-data " method ="post ">
10
18
{% csrf_token %}
11
- < input type ="hidden " name ="author_set-TOTAL_FORMS " v-model ="getTotalAuthorForm () "
19
+ < input type ="hidden " name ="author_set-TOTAL_FORMS " v-model ="getTotalAuthorForms () "
12
20
id ="id_author_set-TOTAL_FORMS ">
13
21
< input type ="hidden " name ="author_set-INITIAL_FORMS " v-model ="getInitialAuthorForms() "
14
22
id ="id_author_set-INITIAL_FORMS ">
29
37
v-bind:id ="'id_author_set-' + author.author_formset_index + '-id' "
30
38
>
31
39
</ p >
32
- < div class ="">
33
- < div >
34
- < strong >
35
- Author [[getIndexAmongVisibleAuthors(author_index) + 1]]
36
- </ strong >
37
- </ div >
38
- < div >
39
- < label v-bind:for ="'id_author_set-' + author.author_formset_index + '-first_name' "> First
40
- name:</ label >
41
- < input type ="text "
42
- v-bind:name ="'author_set-' + author.author_formset_index +'-first_name' "
43
- v-model ="author.first_name "
44
- v-bind:id ="'id_author_set-' + author.author_formset_index + '-first_name' ">
45
- </ div >
46
-
47
- < div >
48
- < label v-bind:for ="'id_author_set-' + author.author_formset_index + '-last_name' "> Last
49
- name:</ label >
50
- < input type ="text "
51
- v-bind:name ="'author_set-' + author.author_formset_index +'-last_name' "
52
- v-model ="author.last_name "
53
- v-bind:id ="'id_author_set-' + author.author_formset_index + '-last_name' ">
54
- </ div >
40
+ < div class ="form-group ">
41
+ < h4 >
42
+ Author
43
+ </ h4 >
44
+ < div class ="form-row ">
45
+ < div class ="col ">
46
+ < label v-bind:for ="'id_author_set-' + author.author_formset_index + '-first_name' "> First
47
+ name:</ label >
48
+ < input type ="text "
49
+ v-bind:name ="'author_set-' + author.author_formset_index +'-first_name' "
50
+ v-model ="author.first_name "
51
+ v-bind:id ="'id_author_set-' + author.author_formset_index + '-first_name' "
52
+ class ="form-control "
53
+ >
54
+ </ div >
55
55
56
- < div >
57
- < label v-bind:for ="'id_author_set-' + author.author_formset_index + '-email' "> Email:</ label >
58
- < input type ="text "
59
- v-bind:name ="'author_set-' + author.author_formset_index +'-email' "
60
- v-model ="author.email "
61
- v-bind:id ="'id_author_set-' + author.author_formset_index + '-email' ">
56
+ < div class ="col ">
57
+ < label v-bind:for ="'id_author_set-' + author.author_formset_index + '-last_name' "> Last
58
+ name:</ label >
59
+ < input type ="text "
60
+ v-bind:name ="'author_set-' + author.author_formset_index +'-last_name' "
61
+ v-model ="author.last_name "
62
+ v-bind:id ="'id_author_set-' + author.author_formset_index + '-last_name' "
63
+ class ="form-control "
64
+ >
65
+ </ div >
62
66
</ div >
63
-
64
67
</ div >
65
68
66
69
<!-- BOOK -->
67
70
< div >
68
71
< input type ="hidden "
69
72
v-bind:name ="'nested_book-author_set-'+author.author_formset_index+'-book_set-TOTAL_FORMS' "
70
73
v-bind:id ="'id_nested_book-author_set-'+author.author_formset_index+'-book_set-TOTAL_FORMS' "
71
- v-model ="getTotalBookForm (author_index) ">
74
+ v-model ="getTotalBookForms (author_index) ">
72
75
< input type ="hidden "
73
76
v-bind:name ="'nested_book-author_set-'+author.author_formset_index+'-book_set-INITIAL_FORMS' "
74
77
v-bind:id ="'id_nested_book-author_set-'+author.author_formset_index+'-book_set-INITIAL_FORMS' "
@@ -100,43 +103,50 @@ <h1>
100
103
>
101
104
</ span >
102
105
103
- < div >
104
- < div >
105
- < strong >
106
- Book [[getIndexAmongVisibleBooks(author_index, book_index) + 1]]
107
- </ strong >
106
+ < div class ="books-form ">
107
+ < h5 >
108
+ Book [[getIndexAmongVisibleBooks(author_index, book_index) + 1]]
109
+
110
+ < span v-show ="getTotalVisibleBooks(author_index) > 1 ">
111
+ < a href ="" v-on:click ="removeBook($event, author_index, book_index) "> [X]</ a >
112
+ </ span >
113
+ </ h5 >
114
+
115
+ < div class ="container ">
116
+ < div class ="row ">
117
+ < div class ="form-group col-xs-5 ">
118
+ < label v-bind:for ="'id_nested_book-author_set-'+author.author_formset_index+'-book_set-'+book.book_formset_index+'-title' "> Title:</ label >
119
+ < input type ="text "
120
+ v-bind:name ="'nested_book-author_set-'+author.author_formset_index+'-book_set-'+book.book_formset_index+'-title' "
121
+ v-model ="book.title "
122
+ v-bind:id ="'id_nested_book-author_set-'+author.author_formset_index+'-book_set-'+book.book_formset_index+'-title' "
123
+ class ="form-control "
124
+ >
125
+ </ div >
126
+ </ div >
127
+ < div class ="row ">
128
+ < div class ="form-group col-xs-5 ">
129
+ < label v-bind:for ="'id_nested_book-author_set-'+author.author_formset_index+'-book_set-'+book.book_formset_index+'-isbn' "> ISBN:</ label >
130
+ < input type ="text "
131
+ v-bind:name ="'nested_book-author_set-'+author.author_formset_index+'-book_set-'+book.book_formset_index+'-isbn' "
132
+ v-model ="book.isbn "
133
+ v-bind:id ="'id_nested_book-author_set-'+author.author_formset_index+'-book_set-'+book.book_formset_index+'-isbn' "
134
+ class ="form-control "
135
+ >
136
+ </ div >
137
+ </ div >
108
138
</ div >
109
139
</ div >
110
-
111
- < div >
112
- < label v-bind:for ="'id_nested_book-author_set-'+author.author_formset_index+'-book_set-'+book.book_formset_index+'-title' "> Title:</ label >
113
- < input type ="text "
114
- v-bind:name ="'nested_book-author_set-'+author.author_formset_index+'-book_set-'+book.book_formset_index+'-title' "
115
- v-model ="book.title "
116
- v-bind:id ="'id_nested_book-author_set-'+author.author_formset_index+'-book_set-'+book.book_formset_index+'-title' ">
117
- </ div >
118
-
119
- < div >
120
- < label v-bind:for ="'id_nested_book-author_set-'+author.author_formset_index+'-book_set-'+book.book_formset_index+'-isbn' "> ISBN:</ label >
121
- < input type ="text "
122
- v-bind:name ="'nested_book-author_set-'+author.author_formset_index+'-book_set-'+book.book_formset_index+'-isbn' "
123
- v-model ="book.isbn "
124
- v-bind:id ="'id_nested_book-author_set-'+author.author_formset_index+'-book_set-'+book.book_formset_index+'-isbn' ">
125
- </ div >
126
-
127
- < div v-show ="getTotalVisibleBooks(author_index) > 1 ">
128
- < a href ="" v-on:click ="removeBook($event, author_index, book_index) "> Remove Book</ a >
129
- </ div >
130
-
131
140
</ div >
132
141
</ div >
133
142
< div >
134
- < a href ="" v-on:click ="addNewBook($event,author_index) "> Add New Book</ a >
143
+ < a href ="" v-on:click ="addNewBook($event,author_index) " role ="button "
144
+ class ="btn btn-outline-primary "> Add New Book</ a >
135
145
</ div >
136
146
</ div >
137
147
< hr />
138
148
< div >
139
- < button type ="submit " value ="Next "> Save</ button >
149
+ < button type ="submit " value ="Next " class =" btn btn-primary btn-lg btn-block " > Save</ button >
140
150
</ div >
141
151
</ form >
142
152
</ div >
155
165
156
166
first_name : '{{ author.first_name.value|default_if_none:"" }}' ,
157
167
last_name : '{{ author.last_name.value|default_if_none:"" }}' ,
158
- email : '{{ author.email.value|default_if_none:"" }}' ,
159
168
160
169
nested_book : [
161
170
{ % if author . nested_book % }
@@ -200,13 +209,10 @@ <h1>
200
209
} ,
201
210
methods : {
202
211
// author
203
- getIndexAmongVisibleAuthors : function ( index ) {
204
- return this . $data . authors . filter ( ( author , i ) => i < index && ! author . marked_for_delete ) . length
205
- } ,
206
212
getInitialAuthorForms : function ( ) {
207
213
return this . $data . authors . filter ( author => ! ! author . id ) . length ;
208
214
} ,
209
- getTotalAuthorForm : function ( ) {
215
+ getTotalAuthorForms : function ( ) {
210
216
return this . $data . authors . map ( author => author . author_formset_index ) . reduce ( ( a , b ) => a > b ? a : b , 0 ) + 1 ;
211
217
} ,
212
218
// books
@@ -219,14 +225,14 @@ <h1>
219
225
getInitialBookForms : function ( author_index ) {
220
226
return this . $data . authors [ author_index ] . nested_book . filter ( book => ! ! book . id ) . length ;
221
227
} ,
222
- getTotalBookForm : function ( author_index ) {
228
+ getTotalBookForms : function ( author_index ) {
223
229
var books = this . $data . authors [ author_index ] . nested_book ;
224
230
return books && books . length || 0 ;
225
231
} ,
226
232
addNewBook : function ( event , author_index ) {
227
233
event . preventDefault ( ) ;
228
234
const default_new_book = {
229
- book_formset_index : this . getTotalBookForm ( author_index ) ,
235
+ book_formset_index : this . getTotalBookForms ( author_index ) ,
230
236
} ;
231
237
this . $data . authors [ author_index ] . nested_book . push ( default_new_book ) ;
232
238
} ,
0 commit comments