Add multiple files using Django admin inline formset - javascript

In the admin portion of my Django app I want to extend how an existing inline formset works. Currently, I have an inline formset for images with 2 fields - name and image. That model looks similar to this:
models.py
class Slideshow(models.Model):
name = models.CharField(max_length=200,blank=True)
image = models.ImageField(max_length=200,upload_to=destination)
...
Now, in Django admin, I can click "Add another" in my inline, and that adds another block of name and image fields to the inline formset. In that form I can select "Choose file" and add an image file (and optionally a name), click Save and all works well using the existing Django admin functionality.
Is there a way for me to add multiple image files at once to this existing inline formset? Say using an HTML multiple file selection?
Example formset row with sample data
<div class="grp-module grp-tbody has_original grp-dynamic-form" id="asset_set0">
<h3 style="display: none;"><b>asset #1</b> sample-banner-444-fff.gif</h3>
<div class="grp-tr">
<div class="grp-td name ">
<input class="vTextField" id="id_asset_set-0-name" maxlength="200" name="asset_set-0-name" type="text" value="test asset">
</div>
<div class="grp-td file ">
<p class="file-upload">Currently: asset_files/2014/02/13/10/52/1392317533/sample-banner-444-fff.gif <br>Change: <input id="id_asset_set-0-file" name="asset_set-0-file" type="file"></p>
</div>
<div class="grp-td grp-tools-container">
<ul class="grp-tools"><li class="grp-delete-handler-container"><input id="id_asset_set-0-DELETE" name="asset_set-0-DELETE" type="checkbox"></li></ul>
</div>
<input id="id_asset_set-0-campaign" name="asset_set-0-campaign" type="hidden" value="25">
<input id="id_asset_set-0-id" name="asset_set-0-id" type="hidden" value="71">
</div>
</div>
Example formset row without data
<div class="grp-module grp-tbody grp-dynamic-form" id="asset_set1">
<h3 style="display: none;"><b>asset #2</b> </h3>
<div class="grp-tr">
<div class="grp-td name ">
<input class="vTextField" id="id_asset_set-1-name" maxlength="200" name="asset_set-1-name" type="text">
</div>
<div class="grp-td file ">
<input id="id_asset_set-1-file" name="asset_set-1-file" type="file">
</div>
<div class="grp-td grp-tools-container">
<ul class="grp-tools"><li></li></ul>
</div>
<input id="id_asset_set-1-campaign" name="asset_set-1-campaign" type="hidden" value="25">
<input id="id_asset_set-1-id" name="asset_set-1-id" type="hidden">
</div>
</div>
By the way, I have reviewed a few other apps, filer and photologue for example, that offer similar functionality at the cost of including several other features that may or may not affect the rest of my application.

Related

How can I pass the value from drop down list as a link for button?

I am creating a web app (using thymeleaf, html, css, javascript) and I ran into a problem. Say I have a search bar and a button like this:
Now this represents the functionality of an app and currently it can only search records from a table by their name. But I want to add some other functions like "search by population", "search by capital" etc. I was planning on creating a drop-down list next to the search bar where these options will be included, and the user will select from that list how he wants to search for a record. I can't see a way to do that. Currently this is a search bar code:
<h4 class="left">
<form ui-jp="parsley" th:action="#{/events/showByState}" th:object="${myState}" method="get">
<div class="row m-b">
<div class="child">Search by State Name:</div>
<div class="child"><input id="filter" type="text" th:field="*{officialStateName}" class="form-control input-sm w-auto inline m-r"/></div>
<div class="child box-3">
<button class="btn">Search!</button>
</div>
</div>
</form>
</h4>
So it is unclear for me how I do this because I need to specify the link for button based on what user will choose from the list. Any help is appreciated!
You can create a <select> element with options whose value indicate what the action of the form should be. Whenever its value changes, you can update the form's action.
document.getElementById('search-by').addEventListener('change', function(e) {
let searchBy = this.value;
console.log(searchBy);
this.form.action = `/events/${searchBy}`;
});
<form ui-jp="parsley" th:action="#{/events/showByState}" th:object="${myState}" method="get">
<div class="row m-b">
<div class="child">Search by
<select id="search-by">
<option value="showByState">State Name</option>
<option value="showByPopulation">Population</option>
<option value="showByCapital">Capital</option>
</select>:</div>
<div class="child"><input id="filter" type="text" th:field="*{officialStateName}" class="form-control input-sm w-auto inline m-r" /></div>
<div class="child box-3">
<button class="btn">Search!</button>
</div>
</div>
</form>

İ can't pull data with JavaScript

I want to pull data using JavaScript and show it in console. I don't know what I did wrong.
main.js
// ADD TO CART
$("#addToCartBtn").on('click',function(){
var _qty=$("#productQty").val();
var _productId=$(".product-id").val();
var _productName=$(".product-name").val();
console.log(_productId,_productName,_qty);
});
I am using django framework to write backend
detail.html
<div class="product-btns">
<div class="qty-input">
<span class="text-uppercase">Ədəd: </span>
<input class="input" type="number" value="1" id="productQty">
</div>
<input type="hidden" class="product-id" value="{{product.id}}">
<input type="hidden" class="product-name" value="{{product.name}}">
<button class="primary-btn add-to-cart"><i class="fa fa-shopping-cart" id="addToCartBtn"></i> Səbətə at</button>
</div>
The problem is probably that the element that has id="addToCartBtn" is not really the button but the <i> element - which has no content and therefore no width. So it is never clickable.

How to remove multiple files uploaded from an array based on user selection in javascript or angular

Hi I need to remove multiple files uploaded from an array based on user selection in javascript or angular.........
I have tried with below code
First we have some files that are uploaded in an array and are displayed in checkboxes as shown below in code
<div *ngFor="let image of imagefilename" style="margin-left:10%">
<label class="container" style="font-size:14px">
{{image.name}} ModifiedDate:{{image.lastModifiedDate}}
<input type="checkbox" style="float:left" value="{{image.name}}" [(ngModel)]="imageChecked"
[name]="image.name">
<span class="checkmark"></span> <br><br>
</label>
</div>
<button *ngIf="imagefilename.length" class="btn btn-danger" type="submit" (click)="resetimage(imagefilename)">Reset Selected files</button>
The user will click on the checkboxes that are to be removed and then click on the button displayed and
it calls a function as displayed below
resetimage(imageName:any) {
for(var i = 0; i<this.imagefilename.length;i++){
if(this.imageChecked){
this.imagefilename.splice(i,1);
}
}
}
So in this function, only the first file in the array is removed although the user has selected multiple files to remove.
So please help me if there is any solution.
Expected result :
to remove multiple files uploaded from an array based on user selection in javascript or angular
Actual result :
Only first file is removed even though the user has selected multiple files.(as per my code)
your property imageChecked is not binded with image. You should add property imageChecked in image and modify html like below.
<div *ngFor="let image of imagefilename" style="margin-left:10%">
<label class="container" style="font-size:14px">
{{image.name}} ModifiedDate:{{image.lastModifiedDate}}
<input type="checkbox" style="float:left" value="{{image.name}}" [(ngModel)]="image.imageChecked"
[name]="image.name">
<span class="checkmark"></span> <br><br>
</label>
</div>
<button *ngIf="imagefilename.length" class="btn btn-danger" type="submit" (click)="resetimage(imagefilename)">Reset Selected files</button>
And you code should be like this
resetimage(imageName:any) {
for(var i =this.imagefilename.length;i--){
if(this.imagefilename[i].imageChecked){
this.imagefilename.splice(i,1);
}
}
}

How to generate a QR code with templated data?

I'm currently using Express, Mustache and QRCode.js.
Currently, when editing a product from the database, a mustache template is used and the /id is added to the end of the URL to specify which product ID will be edited. On this edit page, at the bottom, I was able to create a QR code with QRCode.js that links to the current page. It is to be downloaded and printed on to a sticker, which will go on a shelf. That way, users can scan the QR code with their phone and subtract from the product inventory.
However, I'd really like to add the {{product.productId}}, {{product.Manufacturer}} and {{product.product.Sku}} on the right of that downloadable QR code. That way, they can easily be downloaded and go straight to a printer, instead of having to drop them in an editing program to add the information manually. This is my first back-end product. Would someone give me a roadmap on how to accomplish it?
Here is my code:
<pre>
<div class="generate">
<div class="generate_qrcode" id="output"></div>
</div>
<div class="qrcode__span">Right click to download as a .png</div>
<!-- <img class="QRCode" src="qrcode-encoding.png" /> -->
<script>
let qrcode = new QRCode("output", {
text: window.location.href,
width: 256,
height: 256,
colorDark : "#04243c",
colorLight : "#FFFFFF",
correctLevel : QRCode.CorrectLevel.H
});
</script>
<!-- HTML/Product Edit Field (on same page as above code) -->
<body class="product_edit">
<h2 class="ep__h2">Edit Product</h2>
<div class="ep">
<form class="ep__form"
action="/product_edit/{{product.productId}}" method="POST"
autocomplete="off">
<label for="productname" class="ep__label">Product Name:
</label>
<input type="text" name="product_name" class="ep__input"
placeholder="Product Name" value="{{product.productName}}">
<label for="manufacturer" class="ep__label">Manufacturer:
</label>
<input type="text" name="product_manufacturer"
class="ep__input" placeholder="Manufacturer" value=" .
{{product.productManufacturer}}">
<label for="product_size" class="ep__label">Size:</label>
<input type="text" name="product_size" class="ep__input"
placeholder="Size" value="{{product.productSize}}">
<label for="product_qty" class="ep__label">Quantity:
</label>
<button type="button" class="ep__qtyminus" value="-"
name="product_qty" field="product_qty">-</button>
<input type="number" name="product_qty"
class="ep__qtynumber" value="{{product.productQty}}">
<button type="button" class="ep__qtyplus" value="+"
name="product_qty" field="product_qty">+</button>
<label for="product_sku" class="ep__label--half">SKU:
</label>
<label for="product_minimum" class="ep__label--
half">Minimum:</label>
<input type="text" name="product_sku" class="ep__input--
half" placeholder="SKU" value="{{product.productSku}}">
<input type="number" name="product_minimum"
class="ep__input--half" placeholder="Minimum" value="
{{product.productMinimum}}">
<label for="product_color" class="ep__label--half">Color:
</label>
<label for="product_number" class="ep__label--half">Number:
</label>
<input type="text" name="product_color" class="ep__input--
half" placeholder="Color" value="{{product.productColor}}">
<input type="number" name="product_number"
class="ep__input--half" placeholder="Minimum" value=" .
{{product.productNumber}}">
<button class="ep__save" type="submit">Save</button>
</form>
</div>
</pre>
Typing here for more space:
Assuming you have access to the Express server, why can't you create a route that retrieves all products, and for each unique product, generates a little html that includes name, id, price, and QR code? Then express can compile all the HTML and send it to the browser.
app.get('/products/print_stickers', function(req, res, next){
// below is psuedo code
var products_array = database.getAllProductInfo();
res.render('print_page', {
products: products_array // pass data to mustahce template
});
})
Then in your print_page mustache file, you just loop over information we got from the server. If it contains data for all the products, then we can create the html stickers for every product on just one page!
var sticker_html = `
<ul>
{{#.}}
<li>
<div class="left_side">
${new QRCode("output", {
text: 'http://mywebsite/product/id/{{product_id}}', // using {{ mustache }} to insert product id
width: 256,
height: 256,
colorDark : "#04243c",
colorLight : "#FFFFFF",
correctLevel : QRCode.CorrectLevel.H
})}
</div>
<div class="right_side">
<p>{{name}}</p>
<p>{{date}}</p> // using {{ mustache }} to insert product information
<p>{{price}}</p>
</div>
</li>
{{/.}}
</ul>;
`;
Mustache.render(tmp, products_array);
So at this point, you'd go to this page, and the server would get the products, generate html for each unique item, send it to your browser, you print it, then use scissors to cut them up and post them where you need them. If you need to just print a single sticker, you can use an optional query param with the ID of the product, and say if product_id, then only get 1 product from DB, generate sticker html as normal.

How can I use the same jQuery function for multiple divs without repeating the code

I have a add/remove textfield feature wherein I want to implement a jQuery function to all the textfields in a div.
Can I use the same jQuery function for all the fields in the div or should I write different for each.
DEMO can be got here. In the demo I have made it work for one input field, how can I make it work for the rest.
HTML
<div id="single">
<div id="Ivrgroupzbase_grpzWelcomeNotes" class="row">
<h2><a id="addScnt" href="#">Add Another Input Box</a></h2>
<label for="Ivrgroupzbase_grpzWelcomeNotes">Grpz Welcome Notes</label>
<input type="text" id="Ivrgroupzbase_grpzWelcomeNotes" name="Ivrgroupzbase[grpzWelcomeNotes]" cols="50" rows="6">
</div>
<div id="p_scents" class="row">
<h2><a id="addScnt" href="#">Add Another Input Box</a></h2>
<label for="Ivrgroupzbase_grpzWelcomeNotes">Grpz Welcome Notes</label>
<input type="text" id="Ivrgroupzbase_grpzWelcomeNotes" name="Ivrgroupzbase[grpzWelcomeNotes]" cols="50" rows="6">
</div>
</div>
fiddle http://jsfiddle.net/Drea/28h0L6eb/
html
changed id "addScnt" to class - you should avoid using same id multiple times
js
$('.addScnt').on('click', function (event) {
event.preventDefault();
$(this).closest('.row').append(createInput($('#Ivrgroupzbase_grpzWelcomeNotes p').length + 1), '');
});

Categories

Resources