This section adds the ability to submit and delete recommended books to learn about node's form submission and node's image upload function. Before you start, you can fork:https://github.com/stoneniqiu/readingclub on git first.
First, form verification
MVC form Validation There are three places to do, the first is the front-end submission, the second is before the data is saved, that is, in the controller to do the verification, the third pass is the data preservation, that is, if the data model submitted does not conform to the entity defined constraints, the data can not be saved , this is the last line of defense. The first pass mainly relies on JS or jquery framework, the more commonly used is jquery.validate.js. If ASP. NET MVC can generate validation rules automatically, this is not scrutiny, there are many articles on the web. The second layer is related to the respective business logic, and some necessary validation is required to prevent the front-end from banning JavaScript and submitting illegal data, here is the third layer of verification based on Mongoose.
1. Recalling the model definition
Let's review the book model previously defined with mongoose:
var New Mongoose. Schema ({ true }, rating: { type:number, true, 0 , 5 } ,true }, img:string, Tags: [String], True }, isbn:string,});
Each property defines the type and whether it must be, and you can add other constraints such as Min,max, default, and so on. If the submitted model does not meet these constraints, it cannot be saved successfully. Equivalent to the dataannotations in ASP. The subsequent form validation is based on this.
2. Add a route
We need to add 4 routing rules, 2 for adding (one get, one post), one for deleting, and one for uploading images:
Router. Get ('/book/create ', homecontroller.bookcreateview); router. Post ('/book/create ', homecontroller.dobookcreate); router. Delete ('/book/:id ', HomeController. Delete ); router. Post ('/uploadimg ', homecontroller.uploadimg);
With Express-based routing, we can create restful routing rules. The route is located under the App_server folder.
3. Adding a Controller method
Home.bookcreateview:
function (req, res) { res.render (' Bookcreate ', {title: ' New recommended book ' });
Here is a GET request directly, so render the view directly with render, of course this bookcreate view will be created next.
Dobookcreate:
Module.exports.doBookCreate =function(req, res) {varrequestoptions, Path, postdata; Path= "/api/book"; PostData={title:req.body.title, Info:req.body.info, ISBN:req.body.ISBN, Brief:req.body.brief, Tags:req.body.tags, Img:req.body.img, Rating:req.body.rating,}; Requestoptions={url:apiOptions.server+path, Method:"POST", Json:postdata,}; Request (Requestoptions,function(Err, response, body) {Console.log ("Body.name", Body.name, Response.statuscode); if(Response.statuscode = = 201) {Res.redirect ("/detail/" +body._id); } Else if(Response.statuscode = = && Body.name && body.name = = "ValidationError") {Res.render (' Bookcreate ', {title: ' New recommended book ', Error: ' Val '}); } Else{Console.log ("Body.name", Body.name); Info (res, response.statuscode); } });};
Info
functioninfo (res, status) {vartitle, content; if(Status = = 404) {title= "404, Page Not Found"; Content= "Pro, the page flies away ..."; } Else if(Status = = 500) {title= "500, internal error"; Content= "Embarrassed ..., an error occurred"; } Else{title= Status + ", What's Wrong"; Content= "There may be some mistakes in some places"; } res.status (status); Res.render (' Info ', {title:title, content:content, Status:status,}) ;
View Code
In the previous section, we created the API portion of the data operation. The process of the code is to get the data from req to the front end, and then call the API with the request module, if the add succeeds (the status code is 201) to return to the detail page, if the validation fails, the original path back, and give a hint. If the error, give the info method to handle it.
Delete
Module.exports.Delete=function(req, res) {varrequestoptions, Path; Path= "/api/book/" +req.params.id; Requestoptions={url:apiOptions.server+path, Method:"Delete", JSON: {},}; Request (Requestoptions,function(Err, response, body) {if(Response.statuscode = = 204) {Res.json (1); } Else{Res.json (0); } });};
If the deletion succeeds, the returned status code is 204, and then returns JSON (1) to let the front-end handle the interface.
4. Add a View
1) First add a button to the right sidebar of the book list:
In the books view, modify:
. col-md-3 . UserInfo P Stoneniqiu A (href= '/book/create '). Btn.btn-info New Recommendation
When the user clicks, it jumps to the/book/create page
2) New recommended page:
Extends Layoutinclude _includes/ratingblock content. Row Col-md-12.page.bookdetail h3 new recommended books. Row. Col-xs-12.col-md-6 form.form-horizontal (action= ", method=" post ", role=" form ")-if (Error = = "Val"). Alert.alert-danger (role= "alert") All fields requ Ired, please try again . Form-group Label.control-label (for= ' title ') title Input#name.form-control (name= ' title ') . Form-group Label.control-label (for= ' info ') information Input#name.form-control (name= ' info ') . Form-group Label.control-label (for= ' ISBN ') ISBN Input#name.form-control (name= ' ISBN ') Form-group Label.control-label (for= ' brief ') Introduction Input#name.form-control (name= ' brief ') . Form-group Label.control-label (for= ' tags ') tag input#name.form-control (name= ' tags '). form-g Roup Label.control-label (for= ' rating ') Recommended index SELECT#RATING.FORM-CONTROL.INPUT-SM (name= "rating") Option 5 Option 4 option 3 option 2 option 1. form-gr OUP p upload Image a.btn.btn-info (id= "Upload", name= "upload") Upload image br img (id= ' img ') . form-group Submitted by Button.btn.btn-primary (type= ' submit ')
The place of the IF statement is used to display the error message, the picture is uploaded, and the page is fully introduced;
3) Mongoose Verification
This time without the front end verification, the form can be submitted directly. But node prints out the error log, book validation failed, and the validation fails.
This is the verification information that mongoose returns to us, when the interface displays a prompt message:
This is because of the processing in the controller:
Else if && body.name && body.name = = "validationerror") { Res.render ( Error: "Val"});
This indicates that Mongoose validates the entity when the data is saved and cannot be saved if the entity does not meet the path rule. However, there are three questions, the first problem is that the information is unclear, of course, we can traverse the output validatorerror; the second is that after the validation error, the original data of the page is not available and needs to be entered again, we can refer to the ASP. MVC can be solved by populating the model data into the view; the third problem is that the front end of the page has not been verified, the form can be submitted directly, this can be done by a simple jquery script, which is not scrutiny at three. Continue to look down, if the specification input, this time can be submitted, after submission on the books page can be seen:
4) Delete
Added a delete symbol to the right of the title (in the Books view):
. col-md-10 P A (href= "/detail/#{book._id}") =book.title ×
and add the script:
$ (". Close"). Click (function() { if (confirm) ("OK" to delete? ")) { var id = $ (this). Data (" id "); var row = $ (this). Parents (". Booklist"); $.ajax ({ "/book/" + ID, "Delete", }). Done ( function(data) { console.log (data); Row.fadeout ();});} );
The script can be located just below the layout view:
Script (src= '/javascripts/books.js ')
This will hide the current row after the deletion is complete. Here to solve the picture upload problem.
Second, image upload
We defined a Uploadimg method in the route and now implement it. Generally involves two parts, one is the foreground picture submission, one is the back-end data processing.
1.uploadimg Method implementation
The formidable module needs to be installed first.
Then create a upload/temp folder under the public file
Script:
varFS = require (' FS ');varFormidable = require (' formidable ')); MODULE.EXPORTS.UPLOADIMG=function(req, res) {varform =NewFormidable. Incomingform ();//Create an upload formform.encoding = ' utf-8 ';//Set Edit Form.uploaddir = './. /public/upload/temp/‘;//Set upload directoryForm.keepextensions =true;//reserved suffixForm.maxfieldssize = 3 * 1024 * 1024;//File SizeForm.parse (req,function(Err, fields, files) {console.log (files); if(Err) {Console.log (err); returnRes.json (0); } for(varKeyinchfiles) {Console.log (Files[key].path); varExtname = ";//suffix name Switch(key.type) { Case' Image/pjpeg ': Extname= ' jpg '; Break; Case' Image/jpeg ': Extname= ' jpg '; Break; Case' Image/png ': Case' Image/x-png ': default: Extname= ' png '; Break; } varAvatarname = (NewDate ()). GetTime () + '. ' +Extname; varNewPath = Form.uploaddir +Avatarname; Fs.renamesync (Files[key].path, NewPath); // Renaming returnRes.json ("/upload/temp/" +avatarname); } }); };
This form automatically saves the file to the Uploaddir directory and renames it in the upload_xxxx format, so the file is renamed with the FS module at the end. Then return to the front end.
2. Front End
I like to use plug-in, the front-end I use is plupload-2.1.8, has a variety of upload methods, more convenient. Placed under the public file. Reference JS in Layout.jade:
Script (src= '/plupload-2.1.8/js/plupload.full.min.js ') script (src= '/javascripts/books.js ')
In the Bookcreate.jade view, modify the following:
A.btn.btn-info (id= "Upload", name= "upload") Upload image br img (id= ' img ') input# Imgvalue (type= ' hidden ', Name= ' img', value= ')
A tag is used to trigger uploads, IMG is used for previewing, and input is used to store paths. Add the following code under Books.js:
varuploader =NewPlupload. Uploader ({runtimes:' Html5,flash,silverlight,html4 ', Browse_button: "Upload", URL: '/uploadimg ', Flash_swf_url:'/plupload-2.1.8/js/moxie.swf ', Silverlight_xap_url:'/plupload-2.1.8/js/moxie.xap ', Filters: {max_file_size:"3MB", Mime_types: [{title:"Image Files", Extensions: "Jpg,gif,png"}, {title:"Zip files", Extensions: "Zip"}]}, init: {postinit:function() {}, filesadded:function(up, files) {Plupload.each (Files,function(file) {Uploader.start (); }); }, Uploadprogress:function(up, file) {}, Error:function(up, err) {}}}); Uploader.init (); Uploader.bind (' Fileuploaded ',function(Upldr, File, object) {vardata =json.parse (object.response); Console.log (data); $("#img"). attr ("src", data); $ ("#imgvalue" ). val (data);});
Submit:
Jump to the detail page after uploading successfully.
At this point, the section on the submission of the form learns the Mongoose data validation, as well as the use of plupload uploads, and the backend uses the formidable and FS modules to process the pictures. ASP. NET MVC is relatively fast because it has an automated form. The next section introduces angular, as a in mean.
Source: Https://github.com/stoneniqiu/ReadingClub
Nodejs's mean stack development (iv)--form verification and image uploading