A web interface (draggable elements, remembering state) similar to Wufoo - javascript

The question I have is very specific. I wanted to have an app where I can create forms, as on Wufoo, with easy to use interface. Which means, draggable elements.
My problem is that I cannot figure out how will the state be saved in the database once the use changes the ordinal position of the form elements. I can do the front-end side, and there are libraries available for that but how do I save a particular instance of the form in the backend so that the next time use logs in, the order is same.
I would love to use Django for this app. So, the basic classes I can think of are:
class Form(models.Model):
"""...objects..."""
class TextField(models.Model):
"""...objects..."""
#FK to Form()
class TitleArea(models.Model):
"""...objects..."""
#FK to Form()
I can also have specific ID's on the elements in the HTML form:
<input id="Field2" name="Field2" type="text"/>
How do they (Wufoo) do this? Is my Model not correct? I know it is naive. Thanks.

You can use ModelForm to create forms using a model instance. Just save the model after a user is done editing, and then when you create the form for them again use the model as an instance to your ModelForm (or formset):
form = YourForm(instance=model_instance)

hidden input fields for the win.
suppose:
$("#submitForm").click(function() {
// Check out the state of the union and change the hidden fields accordingly..
// Something like:
for (var i = 0; i < $(".orderedElements").length; i++) {
$("#ordered-" + ((Number) i + 1)).attr('value', $(".orderedElements").eq(i).attr('id'));
}
});
If you catch my drift.

Well, a good place to start is to think about a use-case. If I'm a user, what am I going to need available to me, to build a form? Textfields, sure -- but what else? Is the form going to have a title? A URL? An expiration date?
When you have this kind of information plotted out, then you can start building out your models in Django.

Related

How to get the "input" field value inside a EventListener function from DOM in Angular

Inside my "characters" component I have a form with a textfield, and button. ->
When I click the button it registers, and enters the function but I have no idea how to grab the current input text and use it in the called async function.
HTML:
TS:
Sadly getting the promptText does not work. I have the feeling I am missing a core concept of angular here, but even after extensive search, no luck.
Thanks in advance!
You can use
const promptTxt = document.getElementById('prompt-txtbox') as HTMLInputElement;
console.log(promptTxt.value);
Rather than trying to create form with plain javascipt/jquery, you can use Template form and Reactive form that angular provide to do the same.
A lot of example documentation/video in available for the same.
This seems like something you can also achieve by simple model binding but learning the correct way once will prepare you handle complex forms and build them quickly.

Default value in HTML form (handling roles by views or by default)

I am going to describe the need, I hope to make myself understood: I need to use several forms for users, according to the form filled in as a type of user, in my user model I use the id of another table for role management.
in the html try to insert something like this:
value="9"
However it does not work, I'm using angular and the backend is developed in .Net Core.
If I understood your intention-
Why do not you use Form-group, with form control?
Where you can enter a default value, like this-
fb.group({
yourControl: [0] // '0' is the default value
});
Hope this helps you, and that I understood what you mean.

Thymeleaf+spring+Jquery dynamically added forms

Having troubles getting values from dynamically added dropdown in thymeleaf.
This is my first
<select th:field="${offer.offerItemList[__${iterationStatus.index}__].mapa}" class="form-control input-sm ofa">
<option value="0" >---Choose option---</option>
<option th:each="attribute : ${offer.offerProductAttribute}" th:value="${attribute.id}" th:text="${attribute.name}"></option>
</select>
Based on selecton from this dropdown i am generating another dropdown with code similar to this :
var options = '<select th:field="offer.list" class="form-control input-sm"> <option th:value="0">--Choose--</option>';
$.each(value.offerProductAttributeValuesList, function (index, value) {
options += '<option th:value="' + value.id + '">' + value.value+ '</option>';
});
options+= '</select>';
of.closest('tr').find('td:last').html(options);
Dom elements generate fine. Everything is ok but values are never submitted with the rest of input fields.
I have done this many times but with previously rendered
<select>
dropdown on the server side, and i would just appendTo() options, but in this case i cannot do that since i potentially have more than 20 dropdowns, based on clients selection from previous dropdown.
I hope i am being clear enough about my issue.
I am gonna answer my own question, since it took me quite some time to get around this problem, and my solution will probably help someone in the future.
The problem was : i had list of objects, and each one of those objects had another list of objects.
The problem is much easier to solve if you just render entire view from the backend (i was using thymeleaf). That way you can use thymeleaf expressions to map everything correctly
Like this :
First you gonna need for each to iterate over top level list
<tr th:each="item,iterationStatus : ${offer.offerItemList}">
You need to use iterationStatus to iterate over nested List, like this :
<select th:field="${offer.offerItemList[__${iterationStatus.index}__].mapa}">
This little piece of code __${iterationStatus.index}__ will basically use iteration index and you will end up with number for each iteration and rendered view will look like this offer.offerItemList[0].mapa, and 1 and 2 and so on.
this way values will be mapped correctly, BUT, if you want to add fields dynamically things get a bit more complicated.
There is jquery issue. Since jquery pretty much binds selectors when page is rendering, even if you write add another element, say <div class="temp">
and write perfectly good jquery function something like this $('.temp').on('click',function(){ console.log("clicked")});
nothing will happen since jquery didnt bind your newly created element to any select/event listener. The solution is to use (document).
$(document).on("click",".temp",function(){console.log('clicked');})
ok we have fixed front end issue, now newly created items work, but how do i tell spring to bind them to each object within list, which is part of another list? well you will have to use iteration index again :
When rendering the view you will need to save iteration index value in each element(using hidden fields)
Get value for each input field to jquery var like this : var iteration = $(this).closest('tbody').find('td:first-child').find('input').attr('value'); ofc this is path to where i have placed hidden input field, you will have to tell jquery where to look according to your structure.
You will simulate array and index numbers like this
var options = '<select name="offerItemList['+iteration+'].mapaValues">';
And the very last thing you need to be careful about is this : Say you have Object which you would normally send from controller like this model.addAttribute("offer",offer); object Offer has attribute, list of Products, so you would access that list with simple offer.productsList, but each product has list of AttributeValues. So final setup looks like this
offer.products[0].attributes[0].name products is an arrayList of objects of class Product, attributes is an arrayList of objects of class AttributeValues and name is a String. In order to let spring create object of class AttributeValues with information spring is receiving from dynamically(and non-dinamically) created forms from the frond-end, you will need to teach him how. If your new form with has input type="text" you are sending back String, so you will need to create a Custom constructor for
your class AttributeValues which will receive a String and which will tell Spring how to "construct" instance of that class with String.
finally create two constructors, one default and one with String as a value :
public AttributeValues(){}; and another for String public AttributeValues(String n){this.name = n;};
The problem you're most likely seeing here is that you're generating thymeleaf markup on the client-side.
Thymeleaf is a server-side templating language, so the browser (and hence the Javascript) will only ever see plain HTML coming back.
Here's a few approaches to consider:
submit the form each time to get new data in, which means no javascript is required
Output every possible dropdown into your HTML, and show/hide them as needed when the user selects options. Some fairly simple Javascript required, but as you mention - the page size may be pretty big
Add a JSON endpoint to your Spring webapp (see the spring #ResponseBody annotation) that will return just the data you need, then pull that JSON data in when the user selects a dropdown using something like jQuery.get()

How to use Django-ratings with bootstrap-rating-input

Here goes another star rating question. I want to use bootstrap-rating-input to input rating value (1 to 5) and have django-ratings save the rating to the database. Although I'm a little green with javascript, I really want users to be able to vote using star rating instead of a number input form. Could you show me how to hook up these two apps to make them play nice with each other?
What does the view and templates look like?
And how do I configure the javascript to make the whole thing work?
Thanks!
OK, boostrap-rating-input is not specifically for django, meaning you will have to do some work to get it going.
I suggest you create a widget for it based on the django-bootstrap-datetime-picker which has implemented a similar bootstrap input field to work nicely with django.
Once that is done, you will be able to add a ratinginput widget to your form which will automatically return a number when the form is submitted, as for django ratings, as long as you have a rating = RatingField(range=5) field in your models you can override it with a rating = ratingWidget() and everything else should take care of itself.
I might try implement the widget later today.
Add this in your head part for test:
<script src="https://raw.githubusercontent.com/javiertoledo/bootstrap-rating-input/master/src/bootstrap-rating-input.js"></script>
now add this code where you want to give a rating
<input class="my_class rating" data-clearable=""
data-max="5" data-min="1" id="some_id"
name="your_awesome_parameter" value=""
type="number"
onchange="console.log($('input.my_class').rating().val())"/>
and simply you get the no. of rating in console now make a ajax call and add it to your DB .
Note: In case when you try static ratings for user view use code like that
max.times do |i|
%i{class: "glyphicon glyphicon-star#{'-empty' if i>val}"}
remember download bootstrap-rating-input.js file after success

How to track changes made in a HTML page

I found this situation very interesting and I hope it is to you as well. I have an exhaustive data entry page with 50-70 form elements loaded with pre-populated values.
Now on submit, I need to show in the next page, the form elements that are changed. Values such as, Label, Old Value, New Value.
What will be an ideal way of going about this? I am looking for a generic impl since I would want to reuse it many times. My skills in playing with a HTML DOM is very limited but I can find a way if you can guide me with an approach.
You can add attribute to all <input /> to save the original value.
You can easily do that with jQuery:
$("input").each(function() {
$(this).attr("originalValue", $(this).val());
});
And then compare it with the new value when the user hit the Submit button.
Demo: http://jsfiddle.net/uUGrU/14/

Categories

Resources