Ruby on Rails 4: New action in modal - ruby-on-rails-4

In the index view I have a list of my models and "Create new" button. When user clicks on the button a modal form should be presented with one field: name of the model - the only field that required to create a model. When the user enters the name and click submit button the model get saved and edit view is displayed as a normal page ( with all fields from model available for editing).
How to achieve this? I have tried to build a new object in the index action:
def index
#my_models = MyModel.all
#new_model = MyModel.build
end
but that did not work (I was getting missing template error although without #new_model the index was displayed without problems)
Another question is how to render the form? Should I put the form into new.html.erb file
and then include <%= render 'new' %> in the body of the modal? (I am using Bootstrap 3.1 to create the modal itself)?

You can simply use
#my_model = MyModel.new
and call
<%= render 'form' %>
which uses #my_model.

Related

Populate Django Form field-labels from a database model when calling this Form thru a sidebar menu item

I am new to Python, Django and web programming, so may be this is a dumb question or conceptually a wrong logic. I am trying to call an entry Form from sidebar menu item and want this Form fields to have labels from a database model, so that same form/database model can be used for different purposes. The sidebar menu is populated using Django-MPTT. This form pop ups normally with it's original labels when clicking the menu item, but if I try to set it's field labels from database model with relative labels, it gives error: 'QuerySet' object has no attribute 'task_t3'. May be it is due "GET" request initiated on menu item click. Any solution to achieve this? Following is code lines from views.py where this error occur:
ctlobj = TaskControl.objects.filter(task_group_no=5)
taskdetail_form = TaskDetailForm()
taskdetail_form.task_3.label = ctlobj.task_t3
The problem was resolved by looping over variable ctlobj and then assigning values to field label in required form:
ctlobj = TaskControl.objects.filter(task_group_no=5)
taskdetail_form = TaskDetailForm()
for obj in ctlobj:
taskdetail_form.task_3.label = obj.task_t3

Setting up a custom workflow for the model change-form view

Context
I have a model, let's call it Application.
class Application(models.Model):
# various fields here
status = status = models.CharField(
max_length=100,
choices=APPLICATION_STATUSES,
default=PENDING_STATUS[0],
)
assigned_operator = models.OneToOneField(
settings.AUTH_USER_MODEL,
on_delete=models.PROTECT,
editable=True,
null=True,
)
This model has some fields, but the ones we care here are the status, which is simply a choice field, and the assigned_operator field, which defines a 1-1 relationship with a User instance. This model also has its corresponding ApplicationAdmin view defined.
Description
The requirement is that when trying to edit an Application, from the admin view, the default workflow, where you make whatever changes you want and then simply save the form, should be replaced with the following workflow:
The application form is readonly unless the user is the assigned_operator of the application, in which case the application is editable.
When the user is not the application's assigned_operator the actions at the bottom will be 1 button:
"Assign to myself" - When clicked the Application model is updated to reference the current user as its assigned_operator and the page refreshes
When the user is the application's assigned_operator the actions at the bottom will be 3 buttons:
"Save changes" - Does what default "Save" button does
"Reject" - When clicked changes the status field of the application to the appropriate one
"Accept" - When clicked changes the status field of the application to the appropriate one
The problem
Well, the problem is that I am pretty new with django and I am pretty lost here.
What I know:
How to make the fields of the form editable or read only based on the assigned_operator value. I think I just have to set up a get_readonly_fields and do my checks there. Correct me if wrong.
I can replace the current list of form actions with some custom buttons by adding a change_form_template = "path/to/change_form.html" field to the ApplicationAdmin. An example change_form.html that I have now:
{% extends 'admin/change_form.html' %}
{% block submit_buttons_bottom %}
<div>
<input type="submit" value="Assign to me" class="default" name="????">
</div>
{% endblock %}
What I don't know
How to conditionally show either the "Assign to myself" or the group-of-3-buttons, depending on the assigned_operator value of the Application model.
How to connect those new custom buttons to interact with the models and do stuff on them, when they are clicked
In general how the change_form.html part, which is just a template as far as I know, can know things from the currently displayed model instance and the current user.
While code examples are welcome, I do not ask you to give me the implementation. Clear directives/instructions will do just fine, I just need some guidance
Thanks
UPDATE
I figured how to pass info to the template, by using the change_view method of the ModelAdmin. So now I can conditionally display the appropriate buttons.
UPDATE 2
Just figured out how to also do something to a model once a button is clicked. We can use either response_change or change_view for that (not sure which one is the more "correct" option, but both work. Difference is that change_view runs before the view is even rendered, while response_change runs after the form has been saved and the model updated)
How to conditionally show either the "Assign to myself" or the group-of-3-buttons, depending on the assigned_operator value of the Application model.
By overriding the change_view method of the ModelAdmin in our custom Admin view we can pass extra context to our html templates, as showcased in the docs here. So now we can conditionally display the appropriate buttons, by adding an {% if context_value %} in the template.
How to connect those new custom buttons to interact with the models and do stuff on them, when they are clicked
We can use either response_change or change_view for that on our Admin view. In there we can listen for the value of our button's name in the request.POST values (for example _save etc) and act accordingly
(not sure which one is the more "correct" option to use, the response_change or the change_view but both work. Difference is that change_view runs before the view is even rendered, while response_change runs after the form has been saved and the model updated)
In general how the change_form.html part, which is just a template as far as I know, can know things from the currently displayed model instance and the current user.
A combination of passing it context from the Admin view and listening for button names from the template in the request.POST

Django MultiWidget format_output method and render method

Can anyone explain the format_output method and render method in django Multiwidget.
I have a Select box, a text field for email input and a checkbox. I have created a multiWidget but I want to have a add more feature, like if somebody clicks on the Add More button, javascript will replicate the set of fields that created by the multiWidget.
Also i want to render html like this :
<input type = "text" name=textbox_name[] />
how can I achieve this.
Thanks in advance.
Take a look at Django Formsets and related posts
dynamically add field to a form

django forms - remove "submit" button

I have a simple form that enables selecting an option (radio button). Upon selection the form automatically submits itself (using the onchange attribute):
class MyForm(forms.Form):
choices=forms.ChoiceField( widget=forms.RadioSelect(attrs={'onchange': 'this.form.submit();'}), choices=[(k,k) for k in options],label="choose one")
This is great, only problem is I still have the "submit" button at the bottom of the form when it's rendered. Is it possible, without creating a template, to somehow make the form render without a submit button?
From Django doc:
The form only outputs its own fields;
it is up to you to provide the
surrounding tags and the submit
button.
It means that you probably have the submit button in you template - remove it if you don't need it.

Insert django form into template dynamically using javascript?

I want to add same django form instance on same template. i already add one before and other add dynamically using javascript.
for example 'form" is a django form: newcell.innerHTML = {{ form.firstname }};
The problem is that when i submit the form, in view the request object has only one value (that is not add using javascript). how can i get the values of other form elements values that is added dynamically runtime.
It is something like the "Attach Another File" feature in gmail, where the user is presented with a file upload field and new fields are added to the DOM on the fly as the user clicks to "Attach Another File" plus button
You could always try separating out your FileField into a FileModel.
Take a look at the following pseudo code (as in python based on memory--i've moved over to clojure for now).
models.py
class FileModel(models.Model):
file = models.FileField()
...
class ThingToWhichYoureAttaching(models.Model):
name = models.CharField()
attachments = models.ManyToManyField(FileModel)
...
forms.py
class FileForm(forms.ModelForm):
class Meta:
model=FileModel
class ThingForm(forms.ModelForm):
attachments = forms.MultipleChoiceField()#override the manytomany form field with style field of your choice.
class Meta:
model=ThingToWhichYoureAttaching
When they pop up the window with the PLUS button, show the FileForm but on the main page leave the ThingForm untouched. You can also have an initial FileField on the main page with the ThingForm for people who don't have javascript. Just make sure to process the FileForm BEFORE the ThingForm so that the File is available for the Thing.
When processing the popup form you can use AJAX (i recommend jquery) to submit the FileForm to the server, and return the markup to insert the File in the Attachments field.