I have a template that displays the list of items. It has one checkbox to each item. I want to be able to remove an item from a checkbox when a checkbox is ticked. So I would need a button that deletes an item once a checkbox is selected. Here is my template.
{% for item in items %}
<tr>
<td><input type="checkbox" name="item" value="{{item.pk}}" checked="checked"></td>
<td>{{item.tiptop_id}}</td><td>{{item.alternative_id}}</td><td>{{item.title}}</td>
<td>{{item.type}}</td><td>{{item.format}}</td>
</tr>
{% endfor %}
I would need probably know what to write in my views as well I guess.
Edit:
Not sure why it is still not deleting. check out my views. My edit order form. It is quiet huge. I thought the delete function would do the trick. Anyway take a look.
def edit_order(request, order_no):
# Alot of code here
if request.method == 'POST':
form = forms.OrderForm(request.POST, instance = order)
if form.is_valid() and save_item is not None:
form.save(True)
request.user.message_set.create(message = "The order has been updated successfully.")
return HttpResponse("<script language=\"javascript\" type=\"text/javascript\">window.opener.location = window.opener.location; window.close();</script>")
if status is not None and contact is not None and save_status is not None and delete_item is not None:
try:
for id in status_items:
item = models.StorageItem.objects.get(pk = id)
delete_item = item
delete_item.delete()
current_status = models.ItemStatusHistory(item = item, contact = contact, status = status,
user = request.user)
current_status.save()
except:
pass
request.user.message_set.create(message = "Status successfully changed for {0} items".format(len(status_items)))
You need to write a view that gets the POST data, finds out which checkboxes have been checked, and then deletes the items from the database matched by id.
You probably also want to wrap the view in a decorator to make sure the user has permission to delete things, or check the logged-in user is the same as the owner of the item to be deleted, if that's how you want to do thing.
Or you could use Django's forms framework to handle some of the heavy work.
Deleting objects from the database is in the db model documentation.
These things aren't totally trivial so don't wait too long here for a full solution - get hacking!
[Edit]:
The real issue is being able to delete items from a database on a form submission, not removing rows from a HTML table. See "A Simple Form-Handling Example" on this pageTutorial for form submissions in Django.
[/Edit]
Here's an example you can copy into a .html file on your computer and open in a web browser. It's using simple JavaScript. For something like this, I prefer to use jQuery, but depending on your use, it may be more overhead than you prefer. However, if you need to do a multitude of client-side programming, I highly recommend using jQuery.
Note: I think it's a little messy using parentNode.parentNode.parentNode, but this example purposely uses a table/checkbox configuration as expressed in the original post.
Preferably, I'd assign Id's to the table's rows that correlate with each checkbox so they're easier to access.
I also included a <input type="button"> because it was asked for in the original post. You may want to consider assigning the onclick= event to each checkbox so the user can remove the items as soon as they're clicked. But that's a preference.
<html>
<head>
<script>
function hideCheckedRows() {
var checkboxes = document.getElementsByName("item");
var checkboxes_to_remove = new Array();
var count = 0;
for (var i = 0; i < checkboxes.length; i++) {
if (checkboxes[i].checked == true) {
checkboxes_to_remove[count++] = checkboxes[i];
}
}
for (var i = 0; i < checkboxes_to_remove.length; i++) {
cbx = checkboxes_to_remove[i];
// parentNode.parentNode.parentNode is the <tr>
// parentNode.parentNode is the <td> containing the checkbox
cbx.parentNode.parentNode.parentNode.removeChild(
cbx.parentNode.parentNode);
}
}
</script>
</head>
<body>
<table>
<tr name="table_row">
<td><input type="checkbox" name="item" value="Check1"></td>
<td>Id1</td><td>Alt_Id1</td><td>Title1</td>
<td>Type1</td><td>Format1</td>
</tr>
<tr name="table_row">
<td><input type="checkbox" name="item" value="Check2"></td>
<td>Id2</td><td>Alt_Id2</td><td>Title2</td>
<td>Type2</td><td>Format2</td>
</tr>
<tr name="table_row">
<td><input type="checkbox" name="item" value="Check3"></td>
<td>Id3</td><td>Alt_Id3</td><td>Title3</td>
<td>Type3</td><td>Format3</td>
</tr>
</table>
<input type="button" value="Click to remove checkboxes!"
onclick="hideCheckedRows();"/>
</body>
</html>
Edit:
If you want the item deleted from the database, we need more information. We need to know what kind of database being used and what the server-side code that handles the submit button's "POST" looks like. This example will delete the checkbox from the table in the user's web browser, but it will have no effect on whatever on the database.
You're doing it wrong :) Create a view only for deleting. Send in POST or GET id of the element (or in url), remove the element from db and then as response send your list without the deleted element.
Something like this :
def delete_element(request, id):
el = get_object_or_404(Element, id=id)
if el:
el.delete()
html = render_list(request)
if request.is_ajax():
result = simplejson.dumps({
"html": "html",
}, cls=LazyEncoder)
return HttpResponse(result, mimetype='application/javascript')
def render_list(request):
elements = Element.objects.all()
return render_to_string(template_name, RequestContext(request, {
"element" : elements, })
And then in your template you first call url of delete function with javascript and then on success you update your template with data['html'].
You can ask this guy : http://twitter.com/sasklacz as he's writing some tutorials on ajax in django to give you the exact code needed.
Related
I'm rather new to programming and super new to Flask. I'm implementing an html page which has a few filters on the left and it shows the results on the right.
For example a filter might be "2 people room". Selecting it, it would show only 2 people rooms in the div on the right.
All my data is in a DB.
What's the best way to implement it?
I'm thinking of this way:
- Implement onclick JS function that, when clicking on 2people room filter, it would select a subset of the data (only the 2 people rooms) and then create html for all that data (in Jinja2).
Is here a better way to do so?
thanks
You could use a HTML checkbox.
You could then have some JavaScript that displays the results based on which checkboxes are checked or not.
EDIT
I have quickly made a form here, using pure HTML/JavaScript. What you could do is make a GET request to your flask server using the contents of array. Or just make a basic SQL query to your database: SELECT houses FROM table WHERE rooms=array. ( That's not a valid SQL query, you will have to pass in the numbers properly)
<!DOCTYPE html>
<html>
<body>
<p>Filter Menu</p>
<form action="/action_page.php">
<input type="checkbox" name="room" value="0">Studio<br>
<input type="checkbox" name="room" value="1">One bed<br>
<br>
<input type="button" onclick="myFunction()" value="update filter">
</form>
<script>
function myFunction() {
var form = document.forms[0];
var array = [];
var i;
for (i = 0; i < form.length; i++) {
if (form[i].checked) {
array.push(form[i].value);
}
}
console.log(array)
// Make an SQL query with array
}
</script>
</body>
</html>
In my Django project, I have a page that displays all the instances of a particular model. I want to auto-refresh the page every few seconds, but only update the relevant part of the page.
I'll describe each part. First - I have a Django view. In its simplest form, it looks like this
class MyListView(ListView):
lookup_field = 'uuid'
model = Foo
template_name = 'mylist.html'
def get_queryset(self):
return list(Foo.objects.all()) # finds all my objects from DB
def get_context_data(self, **kwargs):
objects = self.get_queryset()
context = super(MyListView, self).get_context_data(**kwargs)
context['foos'] = objects # this gets passed to html page
return context
So it finds all Foo objects from the database and returns it to the html.
The html page displays a table, where each entry is a row. Furthermore, there is a checkbox at the beginning of each row. Like this
<table id="content">
<thead>
<tr>
<th><input type="checkbox" id="chckHead"/></th>
<th>UUID</th>
<th>Attribute1</th>
<th>Attribute2</th>
</tr>
</thead>
<tbody>
{% for item in foos %}
<tr id="{{ item.uuid }}">
<td>
<input type="checkbox" name="checkboxlist" class="chcktbl" />
</td>
<td><code>{{ item.uuid }}</code></td>
<td>{{ item.attribute1 }}</td>
<td>{{ item.attribute2 }}</td>
</tr>
{% endfor %}
</tbody>
</table>
Now, some of the attributes of the Foo model may get updated in the background, so I want to somehow refresh the page periodically with new data.
I did that in javascript, like this
function setup() {
setTimeout("refreshPage();", 5000);
}
function refreshPage() {
window.location = location.href;
}
$(document).ready(setup);
So every 5 seconds, JS would call refreshPage(), and my page gets refreshed. If the database was changed behind the scenes, my page would reflect it.
The problem with the above is that it refreshes the whole page, which includes the checkbox. So if I had already selected a checkbox, the refresh would reset it to its original state ('not checked').
So, what is the correct way to solve this problem?
Just really high level:
The window.location that you're adding is going to reset the whole page. By this time you've already figured that out. What you're looking for is something could be handled by using a page partial or by using a REST endpoint and pushing it back through the template.
Here are the steps you'll want refreshPage to preform instead.
Save off any values that you think are important
Send an ajax request to get either the partial or json
Render that new information to the page
Put back the values from step one over the values rendered in step 3
More likely you're going to want to wait to do the refreshPage if they're currently editing the area (saves you step 1 and 4). That, may be a choice you've already voted against.
I hope that helps, it's a very non-technical answer but I'm not sure I could give you a very specific answer without knowing A LOT more about your project.
So I am trying to store data to variables on the page when a button is clicked, there are multiple buttons and it needs to store data for that specific button. Each one of these buttons is nested inside a <form onsubmit></form> all the data I need to extra is within this form in different <input> and <div> tags. So using javascript or jquery how can I select the value of a specific and tag. So when the button is clicked on it adds this product to the cart, I want to take the productNumber, price, and quantity and store them to my own variables. When the button is clicked the forum calls onsubmit="ShoppingCartAddAJAX( this ); so I want to store this data in the ShoppingCartAddAJAX function.
Here is what one of the forms on the page looks like.
<form method="post" name="addtocart-501" onsubmit="ShoppingCartAddAJAX( this ); return false;">
<input type="hidden" name="formName" value="ShoppingCartAddAJAX" />
<input type="hidden" name="productNumber" value="758201" />
<input id="qtyproduct" type="hidden" class="hiddenqty" name="dmst_Qty_2805" value="1" />
<div class="price">
<div class="pricenew singleprice">
$7.99
</div>
</div>
</a>
</div>
</div>
</li>
</form>
So I have been trying to get this data by doing something like this.
var pn = $('input[name$="productNumber"]').val();
var qty = $('input[id$="qtyproduct"]').val();
In my javascript file the function looks something like this:
function ShoppingCartAddAJAX(formElement, productNumber) {
var pn = $('formElement.input[name$="productNumber"]').val();
var aa = $('formElement[name$="productNumber"]').val();
var qty = $('input[id$="qtyproduct"]').val();
}
But with alot more code... just showing that the function is passing in formElement and a productNumber.
But this is giving me the product number and quantity of the first product on the page, I need the data for which ever button the user decides to click on and there are multiple ones on the page not just one. I hope that when the button is clicked and that function is fired there is a way to look what forum it came from and then extract that data. I would also like to be able to get the price but it is stored in <div class="pricenew singleprice"> $7.99</div>.
Any help is greatly appreciated.
You are getting the product number and quantity of the first record since you have multiple input fields in the form with the name of productNumber(according to your description). So what basically happens here is when you call $('input[name="productNumber"]').val() jquery returns you the value of the first input field. Instead of that, do something like this inside your ShoppingCartAddAJAX function.
function ShoppingCartAddAJAX(form)
{
// Find child an element inside our form with the id of "qtyproduct"
// I used "find("#qtyproduct")" method so it searches anything nested inside your specific form element
// You can use "children("#qtyproduct")" method also
var qty = $(form).find("#qtyproduct").val();
var pn = $(form).find("input[name='productNumber']").val();
var pp = $(form).find(".pricenew.singleprice").text();
}
Am trying to figure out how to check the state of a ngModel without using a form tag. I don't have wrappers is just basic input element with a ngModel.
All the examples I have found so far are for form validations and in this case, there is no form.
When i tried something like:
HTML
<input type="text" ng-model="lastname">
SCRIPT:
if($scope.lastname.$dirty) {
console.log('last name has changed');
}
I get undefined.
Is there a way to check the state of the ngModel without adding a watch directive to it? it seems it would be something basic that is part of the framework. Why wouldn't this work?
There are two ways:
1. Use ng-form:
<span ng-form="myForm">
<input type="text" name="name" ng-model="name" required/>
</span>
Now you can access the model either at $scope.myForm.namein your controller or with myForm.name in your view:
var isPristine = $scope.myForm.name.$pristine;
2. Use angular.element().controller('ngModel') (Don't do this one, bad bad bad)
Alternatively, you could hack your way around it. But this is going to be ugly, untestable, and gross:
var elem = angular.element(document.getElementById('myElement'));
var model = elem.controller('ngModel');
var isPristine = model.$pristine;
Edit: Your situation (per your comment) inside of a repeater
the only difference between my example and your is that the input field is inside a ng-repeater. Thought that wouldn't matter but I guess it does.
And now it's time to ask yourself what you're doing and why... You can still get the information you need using ng-form, but you'll need to do some crazy stuff I wouldn't recommend:
<div ng-repeater="item in items track by $index">
<span ng-form="rptrForm">
<input type="text" name="name" ng-model="item.name" required/>
</span>
</div>
.. commence craziness:
// get the first child scope (from the repeater)
var child = $scope.$$childHead;
while(child) {
var isPristine = child.rptrForm.$pristine;
var item = child.item;
if(!isPristine) {
// do something with item
}
child = child.$$nextSibling;
}
It's probably time to rethink your strategy
I'm not sure what your end goal is, but you might want to rethink how you're going about it and why. Why do you need programmatic access to $pristine in your controller? What alternatives are there? Etc.
I, for one, would try to leverage an ng-change event and update some flag on my item in my repeater, and leave the ng-form stuff for validation:
<div ng-repeat="item in items track by $index" ng-form="rptrForm">
<input type="text" name="name" ng-model="item.name" ng-change="item.nameChanged = true" required/>
<span ng-show="rptrForm.name.$error.required>Required</span>
</div>
If you give the <form> element a name attribute, then the <form> will be
added to the $scope object as a property.
Field controller will then be attached to the form property.
As weird as it could seem, you have to define an enclosing form with a name attribute like so:
<form name="myForm">
<input type="text" name="lastName" ng-model="lastname">
</form>
and call the property with:
$scope.myForm.lastname.$dirty
Indeed, ngModelController (field) is attached to ngFormController (form).
I used Ben Lesh's answer to deal with the same problem. I was displaying a list of notification preferences, and my goal was to hit my api with models that had changed. Not just ng-changed, either; value changed.
I start by initializing some private state on my controller:
// Private state
var originalModels = {};
var changedModels = [];
Then I store copies of the original models retrieved from the API:
// Create a hash of copies of our incoming data, keyed by the unique Code
for (var i = 0; i <= data.length - 1; i++) {
var np = data[i];
originalModels[np.Code] = angular.copy(np);
}
Next, we want to make sure that when a model changes, we add it to a changed models collection (or remove it from the collection if no real change occurred):
function modelChanged(m) {
var originalModel = originalModels[m.Code];
var hasChanged = !angular.equals(originalModel, m);
// If the model has changed and is not present in our collection of changed models, add it
if (hasChanged && changedModels.indexOf(m) === -1) {
changedModels.push(m);
}
// If the model has not changed and is present in our collection of changed models, remove it
if (!hasChanged && changedModels.indexOf(m) > -1) {
var i = changedModels.indexOf(m);
changedModels.splice(i, 1);
}
}
Finally, we tie these together in our ng-repeat:
<tr ng-repeat="np in npc.notificationPreferences">
<td>{{np.DisplayName}}</td>
<td>
<input type="checkbox"
ng-model="np.Sms"
ng-checked="np.Sms"
ng-disabled="!np.SmsEnabled"
ng-change="npc.modelChanged(np)"/>
</td>
</tr>
Now, instead of pushing back every row to my API, I simply push the changed models. This also has a side benefit of being able to ng-disable your submit button if nothing has actually changed (ie the changedModels collection is empty).
I am not a JavaScript person really, I write in ASP and use a SQL database in the backend. But our marketing director requested a change that will use JavaScript.
On our view cart page, we're currently displaying an input box with a modify button to allow customers to change the quantity of the listed item (in that row... there could be multiple products in their cart, each having their own quantity input).
<form method="post" action="updateitem.asp">
<input type="hidden" name="product_id" value="<%= PRODUCT_ID %>">
Quantity: <input type"text" name="quantity">
<input type="image" name="Submit" src="/graphics/modify.gif" align="middle" border="0" alt="Continue">
</form>
What I'd like to make work is something like this. Hrm, assuming I need to do my form/div name differently for each product? I can easily write the product_id into the id tags but then assuming I'd also need to loop through my function for each one. I've gotten this far in writing the replacement code:
Get Dataset from Database (items in cart) and loop through:
<form method="post" action="updateitem.asp" id="updateitems<%= PRODUCT_ID %>">
Quantity: <input type="text" name="qty<%= PRODUCT_ID %>" OnChange="Javascript:UpdateQty()")
<div id="showlink<%= PRODUCT_ID %>">
<br /><span class="BodyTiny">update</span>
</div>
</form>
END LOOP
So if the quantity changes, it displays the word "update" where they can click and it passes whatever quantity that is in the quantity field to the updateitem.asp (in a way I can then update it in the database in ASP/SQL). In the code above, if we could just insert the new # in the a href statement after quantity=, then I could fix it in the updateitems.asp page without a problem.
I'm not sure where to even begin honestly, I have this so far:
LOOP through dataset so each product has its own function
<script Language="JavaScript">
<!--
function UpdateQty(updateitems<%= PRODUCT_ID %>) {
Show div updateitems<%= PRODUCT_ID %>
Replace NEWQUANT within that div with the value in the input field qty<%= PRODUCT_ID %>
}
//-->
</script>
END LOOP
I'm having a few problems...
I am not sure how to write the function UpdateQty. It should A) display the stuff in div id=showlink, and B) add the # from the input named quantity quantity to the href so I can update it in the database on the next page
If they have JavaScript turned off, they should be able to enter a new quantity and just hit enter for it to submit the form. I believe this will work as its a form with 1 text input and 1 hidden one, so just hitting enter in the text input should submit it. But that should still work with whatever JavaScript is added to make the showlink div show if it changes.
Do I need to add a class to my CSS for showlink? If so, what do I need to put in it?
Any help would be greatly appreciated!
Mahalo!
so what you can do for updateQty is have one function that will be correct for all products in a list just by making a function that finds all the necessary elements by relative paths.
//in this function the context is the element, so the
//`this` variable can be used rather than a param
//for the product id
function updateQty() {
//show the update link
var parent = this.parentNode;
//assumes only the update text uses the class bodyTiny, and that there
//is only one element using it. obviously making this invariant true
//would be trivial by adding a different class name
var updateText = parent.getElementsByClassName("bodyTiny")[0];
updateText.style.display = 'block';
var updateLink = updateText.parentNode
, updateHref = updateLink.href;
//next we find the current quantity and replace it with the input
updateHref = updateHref.replace(/qty=(\d*)/, 'qty='+this.value);
//then we set the link element's attribute
updateLink.href = updateHref;
//now when you mouse over the link you should see the url has changed
}
You can also set your form to POST the equivalent data, and then I guess on the server side you will have your OnGetPage and OnPostback both delegate to the same method with the parameters either parsed out of the query string or out of the post data.
You can see it running on jsfiddle. Hopefully this helps!