Send a POST ajax to add products to quotation - ajax

My background is more server-side than front-end. So I may be lacking in some basic front-end knowledge.
I have a endpoint called
/quotations/:id/products
which if you do a POST action, this means you want to add products to the specified quotation where :id represents the quotation id.
In my schema, quotations and products have a many-to-many relationship.
The endpoint also expects the data is sent in the form of products[].
Meaning to say, if I want to add products with id 2, 7, and 154 to the quotation 3
I am POSTING
<input name="products[]" value="2" />
<input name="products[]" value="7" />
<input name="products[]" value="154" />
to the url /quotations/3/products
My question is how do I create the Model and View using Backbone for this setup?
I bought Addy Osmani's book on Developing Backbone.js Applications. So I have setup my backbone similar to his example.
There is only an example of a straight forward add model.
Hopefully I get an answer that follows the convention that Osmani sets out for adding children to a parent type of behavior.
Osmani also mentioned about Backbone Relational.
I am not sure if I should use this or even how. I have read the documentation, but I am not sure how to fit this into the way Osmani has structured his Backbone example apps.
UPDATE:
If it is a success, I want the page to redirect to another page called /success.
If it is a failure, I want the page to display a failure message somewhere. Assume there is a <div id="message"></div> for me to update.
In other words, for failure, the page stays as a single page app.
For success, the page goes to another page.
As for server-side code for returning JSON replies etc, I can do this without any problems. Assume I use PHP.

I faced a similar problem recently, I can't tell your for certain this is the best way to do it but it's the way i've found to work reliably. I tried BackboneRelational but was having troubles with it.
This assumes you will need to create the Quote object & ProductQuotation in 1 step.
Set up a view for New Quote
On initialization of this view:
A) Create a new empty Quote model
B) Create a new collection for ProductQuotes
C) Create a new ProductQuote view for each ProductQuote you're adding
D) Subscribe the Quote view to a custom Backbones event binding (Backbone JS: can one view trigger updates in other views?), i.e.
Backbone.pubSub.on('quote_new-product-save', this.AddProduct, this)
This view will now call AddProduct any time you trigger this event.
On initializing each ProductQuote view create a new Product model
Wire this view up for your user to fill in any applicable information & when they are done set this information to that views Product model & trigger the "quote_new-product-save" event mentioned above and pass it that product model.
Back in the Quote view, AddProduct will automatically be called as it was binded to this event. You should wire this to receive the new Product model & add it to the ProductQuotes collection.
So now you have your Product model data set to your ProductQuotes collection but this is still not directly linked to the current Quote (which still hasn't been saved) so set the 'order_items' attribute on your model to all models in your ProductQuote collection i.e.
this.model.set('product_quotes', this.collection.models)
Now your unsaved Quote model will have all members of your ProductQuotes collection set as an attribute.
Now you'll need to call save on the Quote model & send the data to the server. Things to keep in mind here is that your urlRoot is set properly & that the data being sent to the server is being properly formatted. I recommend reading Saving nested objects with Rails, backbone.js, and accepts_nested_attributes_for about overriding the toJSON method in your Quote model.

Related

Why does Laravel group RESTful methods the way they do?

I'm brand new to Laravel and am working my way through the Laravel 6 from Scratch course over at Laracasts. The course is free but I can't afford a Laracasts membership so I can't ask questions there.
I've finished the first several sections of the course and am a little confused about some of the concepts around the whole RESTful idea. The instructor, who seems very good and experienced with Laravel, describes 7 methods that are going to be part of pretty much any CRUD (Create Read Update Delete) application (and most applications are CRUD in nature.) He says naming of these 7 methods should be consistent with this:
index - a list of all the resources in a collection e.g. all articles in a blog
show - display a specific resource from a collection e.g. a specific article in a blog
create - create a new instance of a resource e.g. add a new article to a blog
store - save a new instance of a resource to a data store like a database
edit - modify the contents of an existing resource e.g. change the title of an article
update - save the modified resource to a data store
destroy - remove a resource from a collection e.g. delete a blog article
I'm a little puzzled by this division of work into 7 separate methods. It seems to me that Create and Store belong together in a single method; ditto for Edit and Update. Creating a new record has two phases: displaying an empty form to gather up the data needed to construct a new article, then validating the data and storing it on the database. By the same token, changing an existing record consists of two phases: displaying the current data in a form and letting the user change what needs changing, then validating it and sending it to the database (or back to the user for corrections).
I would also argue that to be consistent with the approach they've used for create/store and edit/update, destroy should be divided into two methods, Destroy and Remove, where Destroy displays the full record that the user wants to remove with two buttons at the bottom: Delete and Cancel. Then, if the user clicks on Delete, they go to a Remove method that actually deletes the record f from the database.
I've been coding for a fair while and I've never seen a system where the user was allowed to delete any important record without first being shown the record and being asked if they're sure they want to delete it. Now, maybe that's fallen out of fashion and I didn't notice but it seems a pretty prudent thing to do.
So why are the methods what they are, at least as RESTful is implemented in Laravel?
It seems to me that Create and Store belong together in a single method
Well, Laravel generate all those methods thinking in a server-side rendered app. So in a SSR, before you store your data, you must be able to see a creation form.. that's why this create() function exists. The create(), normally, should return a view that will show the user the valid fields to create a resource, this is all done in a GET request. Then, when the users hit the "create"/"add" button, it will reach the store() method that will implement the logic to persist this data storing a new record in your database, this is done in a POST request.
The same goes for edit()/update().
I've been coding for a fair while and I've never seen a system where the user was allowed to delete any important record without first being shown the record and being asked if they're sure they want to delete it
That is because those validations are commonly implemented in the client-side, so, you do this with JS in your front-end, for validations of that kind you shouldn't hit the server.
So why are the methods what they are, at least as RESTful is implemented in Laravel?
Finally, for a RESTful API you don't need all of those methods. Just index, show, store, update and delete ones. If you just need this kind of methods in your controller, you could exclude the create/edit ones by adding the --api flag when creating your controller through Artisan. From the documentation:
API Resource Routes
// ...
To quickly generate an API resource controller that does not include the create or edit methods, use the --api switch when executing the make:controller command:
php artisan make:controller API/PhotoController --api

Passing data from one view to another in Laravel

I have a Controller that parses an XML and returns a view with a list of names and URLs.
return view('view_1',compact('myList'));
View_1 will have a form with parameters method="POST" action="goToView_2"
Then I get some information from my view_2 through a POST, but I still want to keep $myList so that view_2 view uses it aswell.
How do I pass $myList from the first view to the next through a controller?
It sounds like you're trying to have multi-step form of some kind.
I would store the data in the session and easily access it in the second controller or in the view (although not recommended).
https://laravel.com/docs/5.4/session#using-the-session
PS. I personally love using the global session helper.

Symfony Good practice : How to embed several forms for a single entity, handled by different controllers

I'm working on an application with Symfony 2 and I'm quite new with this framework.
I would like to create a page that represent an user profile on which users can update their personal information, set up an profile picture and a cover picture.
I've written the code for the User class and the template. For both profile and cover picture i'm using ajax with formdata to send images to server.
The other fields (username, email, etc.) are also sent with ajax, but all three parts (profile picture, cover picture, textual fields) of the form have their own submit button.
My problem is about creating controllers and forms.
Should I create a controller for rendering the profile page and then one controller for handling the form ?
Should I create a single form for all fields on the page or create three separated forms that would be handled separately ?
Should I use formbuilder to create form(s) and in the case of there are more than a single controller, how to retrieve the form created in the first controller in the others to proceed validation
Or maybe am I wrong from the beginning ... ?
I can provide my current code, but I don't think it can be useful since my User class and my template are very basic and I'm stuck on writing the rest of the code ; and I prefer knowing the "good" way of doing it before writing too much trash code.
You can have many form and validate them in one controller:
public function updateAction(Request $request)
{
$form_one = $this->get('form.factory')
->createNamedBuilder('form_one', 'form')
->add('user_picture', 'file')
->add('submit', 'submit')
->getForm()
->handleRequest($request);
// Next form ...
if ($form_one->isValid())
{
// Save user picture
$data = 'user picture saved';
}
// Other forms validation
return new JsonResponse(data);
}
Make sure to create the same forms in user profile controller view.
Should I use formbuilder to create form(s) and in the case of there
are more than a single controller, how to retrieve the form created in
the first controller in the others to proceed validation
You could make formType, like in this example, there is RegistrationType.
Then use formType in different controllers.
Then you could validate form from entity(or whatever doctrine,propel or whatever you are using) using entity validators
You could also check generator bundle, specially Generating a New Form Type Class Based on a Doctrine Entity
Symfony best practices say to use custom form type classes for forms
link
I always use seperate controller actions for seperate forms. Code becomes more organized and is easier to debug. And I have had issues/bugs with multiple forms in same controller.

Symfony2 and filter, right strategy

I'm asking what is the best strategy for filtering with Symfony2.
I want to filter a table of entities (hotels). This filter should allow me to :
choose hotels with or whitout email, with or without web site etc.
choose hotels based on state and/or city (relation OneToMany)
choose what information I want to display on the table with checkboxs (for example display "email adress" on the hotel table, but do not display "tel" or "web site").
First I think to build the filter form on the HotelController. When the filter is submitted, I had a FlashBag for every $_POST sended, redirect to the same page, and if there are FlashBag I send cookies to the $reponse. Then I display the table filtered with data who are on the cookie.
But I dont't really like this, cause I had a very big indexAction() on the HotelController, and I think it'as not really clean to change $_POST to FlasBag to Cookie, is it ? I do this redirection, cause by refreshing the page, data are not posted again.
I'm also asking a question, to prevent a too big IndexAction() method, can I put some code to another method, for exemple a method PostToFlashBag() and another FlashBagToCookie(), or every method on a Controller has to end with the word "Action" and must be accessible with the router ?
Then, I think to another thing : had an entity "Filter", with every row I need. For exemple "WithEmail", "DisplayTel" etc.. Then I can build a FilterType easily, and update the Filter entitie, to redirect to the same page (again, to prevent reposting data if the user refreshes the page). Finally, I can display the table with the object Filter, with a method on the HotelRepository.
That seems great, but I'm a little worry because the filter entity will only have one entry, and I have to find the Filter(1). Due to MVC, is it correct to have a model with only one entry ?
What strategy would you choose (maybe another one) ? I'm interesting to learn good practice with MVC and Symfony2 devloppemnt.
Having a dedicated model class - let's call it Filter - that will receive the values input by the user, is definitely the way to go.
More over, use the Symfony2 form on this input, so you can have validation, and be sure that the withEmailis trully a boolean, etc. From you Filter, build you SQL/Doctrine query and return what your controller have to return, be it a view, or raw datas.
You can have any method you want in a controller. After all, controllers in Symfony2 are plain old PHP objects. They only have to implement ContainerAwareInterface. Usually they inherits Controller, but this inheritance only brings some proxy methods, like getDoctrine or render.
The only convention is that methods which are used as route must end with Action

Form from another model in a view

So I'm trying to extend the Blog tutorial adding some comments:
Post hasMany Comments
I want to display the add comment form in the same view as the 'post view'. Thing is I don't know the best way to get this approach. I thought about three ways:
Creating a function in Comments Controller to handle the data.
Creating a function in Post Controller to handle the data.
Deal with the data in the same function that deals with the post views.
The main problem with the two first 'solutions' is that the validation errors doesn't show up in the form unless I do some messy hacking of saving the invalidated field in a session variable and then parsing the variable on the beforeFilter callback, like this:
function beforeFilter () {
if ($this->Session->check('comment_error')) {
$this->Post->Comment->validationErrors = $this->Session->read('comment_error');
$this->Session->delete('comment_error');
}
}
What I basically do is adapt the invalidated fields to the actual view and allow it to show properly. This works really well, but it seems so ugly to me. What would be the best approach?
Another related question: should a controller reflect a view? I mean on that example, I thought about only having a Comment Model and dealing with all the data in the controller where's the form to add a comment (even though it's in the Post Controller).
Sounds like you're looking for the Mutlivalidatable behaviour: http://bakery.cakephp.org/articles/dardosordi/2008/07/29/multivalidatablebehavior-using-many-validation-rulesets-per-model
This allows you to define more than 1 validation ruleset per model. Use your controller to determine which one to apply upon posting something.
P.S. I have only ever used this on a Cake 1.3 project, not sure if it'll work on 2.0.
I see it this way:
Under every post there is an input box "Add comment" with a button to submit.
After submitting some text a form redirects to comments_controller where the comment is saved with this post_id, body, author, date etc.
After the comment is saved and all the logic is done it takes you back to the post.
Under each post there are all related comments displayed (having the same post_id sorted by date or whatever).

Resources