Dynamically adding new item extremly slow - javascript

I use ASP.NET MVC and Razor. User needs to populate some form which consists of list of objects. So I pass list of empty objects from controller to view. This is part of my main view:
foreach ( var product in Model.Products )
{
Html.RenderPartial( "ProductPartial", product );
}
In ProductPartial user enters some fields for each product.
User can dynamically add or remove products from list. Removing I solved with jquery live function, and it is fine. But I have problem with adding new products.
I solved it in this way: On plus sign click javascript function calls controller action:
public ActionResult NewProduct()
{
Product product = new Product();
product.UniqueId = Guid.NewGuid();
return PartialView( "ProductPartial", product );
}
I need unique id for every product because I want to be able to access products from jquery by ids.
Adding works correctly, but it is extremly slow, since I go on server for every new product. Is there some good way to make it faster?

Well, instead of asking the server for more of the same HTML, you could use jQuery.clone();
In the example I'm copying the first product in the list and giving it a new id, and then adding the copy to the end of the list.
var newProductHtml = $('.MyProducts')[0].clone();
newProductHtml.attr('id', MyNewId);
newProductHtml.appendTo('.MyProductsContainer');

Related

Programmatically add products to a cart – Odoo 13

I have a custom module that creates a form. Based on the answers inside this form I’m generating order line. After user sends this form I’m creating sale order with all products from the generated order line.
So from JavaScript I’m sending an JSON with products to buy:
order_data = [{product_id: 1, amount: 10, …},{product_id: 2, …}, …];
note = '';
this._rpc({
route: '/api/create_order',
params: { order_products: order_data, note: note }
}).then((data) => {
window.location = '/contactus-thank-you';
}).catch((error) => {
console.error(error);
});
And then inside Python I’m creating sale order based on the JSON:
#http.route('/api/create_order', type='json', auth='user', website=True)
def create_order(self, **kw):
uid = http.request.env.context.get('uid')
partner_id = http.request.env['res.users'].search([('id','=',uid)]).partner_id.id
order_products = kw.get('order_products', [])
note = kw.get('note', '')
order_line = []
for product in order_products:
amount = 0
if 'custom_amount' in product:
amount = product['custom_amount']
else:
amount = product['amount']
if amount > 0:
order_line.append(
(0, 0, {
'product_id': product['product_id'],
'product_uom_qty': amount,
}))
order_data = {
'name': http.request.env['ir.sequence'].with_user(SUPERUSER_ID).next_by_code('sale.order') or _('New'),
'partner_id': partner_id,
'order_line': order_line,
'note': note,
}
result_insert_record = http.request.env['sale.order'].with_user(SUPERUSER_ID).create(order_data)
return result_insert_record.id
But instead of generating sale order directly I need to use workflow from Odoo’s eCommerce addon. That way user can for example edit delivery address, choose payment etc. So I think I just need to programmatically put all the product inside a cart and then rest will be taken care of by Odoo built-in functionality.
But how? I’ve tried to find something inside Odoo source code but it is quite hard to grasp anything.
Odoo uses a typical Sale Order for handling products inside a cart. But the process isn't as simple as just creating Sale Order with some products. Odoo needs to know which order is linked with which cart etc.
Luckily Odoo has a method for dealing with it. There is a sale_get_order() method that lets you get an order that is currently linked with a cart or create new one if there isn't any.
I'm not sure if it is documented anywhere outside the source code so here is a slice from the code (/addons/website_sale/models/website.py):
def sale_get_order(self, force_create=False, code=None, update_pricelist=False, force_pricelist=False):
""" Return the current sales order after mofications specified by params.
:param bool force_create: Create sales order if not already existing
:param str code: Code to force a pricelist (promo code)
If empty, it's a special case to reset the pricelist with the first available else the default.
:param bool update_pricelist: Force to recompute all the lines from sales order to adapt the price with the current pricelist.
:param int force_pricelist: pricelist_id - if set, we change the pricelist with this one
:returns: browse record for the current sales order
"""
# ...
I'm using it alongside another method _cart_update() that lets me easily update products inside this order. There is also sale_reset() and I'm using it just to be sure that current session will be updated with particular sale order every time.
sale_order = request.website.sale_get_order(force_create=True)
request.website.sale_reset()
sale_order.write({'order_line':[(5, 0, 0)]})
for product in order_products:
sale_order._cart_update(product_id=product['product_id'], line_id=None, add_qty=None, set_qty=product['amount'])

Jquery exporting table to csv hidden table cells

I need to be able to export a HTML table to CSV. I found a snippet somewhere; it works but not entirely how I want it to.
In my table (in the fiddle) I have hidden fields, I just use quick n dirty inline styling and inline onclicks to swap between what you see.
What I want with the export is that it selects the table as currently displayed. so only the td's where style="display:table-cell". I know how to do this in normal JS.
document.querySelectorAll('td[style="display:table-cell"])');
but how can I do this using the code I have right now in the exportTableToCSV function?
(sorry but the text in the fiddle is in dutch as its a direct copy of the live version).
The fiddle:
http://jsfiddle.net/5hfcjkdh/
In your grabRow method you can filter out the hidden table cells using jQuery's :visible selector. Below is an example
function grabRow(i, row) {
var $row = $(row);
//for some reason $cols = $row.find('td') || $row.find('th') won't work...
//Added :visisble to ignore hidden ones
var $cols = $row.find('td:visible');
if (!$cols.length) $cols = $row.find('th:visible');
return $cols.map(grabCol)
.get().join(tmpColDelim);
}
Here's how i solved it. Decided to step away from a pure javascript solution to take processing stress off the client and instead handle it server side.
Because i already get the data from the database using a stored procedure i use this to just get the dataset again and convert it into an ViewExportModel so i have a TotalViewExport and a few trimmed variations (reuse most of them) based on a Selected variable i fill a different model.
Added to the excisting show function to update a Selected variable to keep track of the currently selected view.
When the user clicks Export table to excel it calls to the controller of the current page, IE. AlarmReport (so AlarmReportController) and i created the action ExportReports(int? SelectedView);
In addition i added CsvExport as a manager. This takes data results (so c# models/ iqueryables/ lists/ etc). and puts them into a Csv set. using the return type BinaryContent one can export a .csv file with this data.
The action ExportReports calls the stored procedure with the selectedview parameter. The result gets pumped into the correct model. this model is pumped into the CsvExport model as rows.
The filename is made based on the selected view + What object is selected + current date(yyyy-MM-dd). so for example "Total_Dolfinarium_2016-05-13". lets
lastly the action returns the .csv file as download using the BinaryContent Returntype and ExportToBytes from the CsvExport
The export part of this action is programmed like so(shortened to leave some checks out like multiple objects selected etc)(data and objectnames are gathred beforehand):
public ActionResult ExportCsv(CsvExport Data, string ObjectName, string Type){
var FileName = Type + "_" + ObjectName + "_" + DateTime.Now.ToString("yyyy/MM/dd");
return BinaryContent("text/csv", FileName + ".csv", Data.ExportToBytes());
}

Disable selected items in multiple drop down lists

Setup
I have a list of drop down lists that are all identical (think row item in a grid). They can be added dynamically and all contain the same list of items. My client has requested that items that are selected in one list should be disabled in all of the other lists.
Everything works except the newly added lists do not have their items disabled (the existing ones do).
The Code
This is broken into a series of function calls but I have munged it here for easier viewing:
function DoTheStuff()
{
enableAllTheDropDownItems(); //This works
var allLists = $(".fooSelections");
allLists.each(function(itemIndex, selectList){
var selectedItems = $(".fooSelections option[selected='selected']");
selectedItems.each(function(index, element) {
var selectedValue = $(element).val();
var parent = $(element).parent();
//skips an item if it is the selectedItem of the current list
if(parent.is(selectList)){
return true;
}
$("option[value*='" + selectedValue + "']", selectList).attr('disabled', 'disabled');
});
});
}
I am using Templates (Editor/Display) to show this partial view but essentially the Razor syntax that creates each Select list looks like this:
#Html.DropDownListFor(m => m.FooId, new SelectList(Model.Foos, "FooId", "FooName", Model.FooId), new { #class = "fooSelections" })
Handlers
I call this in the ajax call that adds a record and the change event of any of the select lists. As I stated before, it seems to work fine for any lists that existed when the Partial View was loaded (asp.NET MVC 4) but not for the items added dynamically (their lists are populated but all of the items are enabled). Even when a second dynamic item is added the first one (added in a different action) doesn't have its items disabled.
Question
Anyone see what I am missing? Or is there a better way to accomplish this same thing?
EDIT : Added missing bracket that Robin caught.
I assume you are using razor ajax helper methods to do the ajax call.
In your ajax helper method #Ajax.ActionLink, you can provide a AjaxOptions object in which you can set a JS method to execute on the OnComplete property
Example:
#Ajax.ActionLink("linkText", "actionName", new AjaxOptions {UpdateTargetId = "DomID", OnComplete = "DoTheStuff" })
In case you are not using ajax helpers and using native ajax call or jquery ajax call, just call "DoTheStuff" method in the ajax success callback.
I improved your example and tested it in a fiddle. Please have a look at http://jsfiddle.net/eJudx/

I'm getting a "newItem() was not passed an identity for the new item" error while trying to add a new item to a JSON store

I've seen other posts in this site regarding the same issue and I've tried the solutions given. I've also visited the links that may offer a solution but I'm still stuck with the same error.
I'm using DOJO and something as simple as this won't even work
myStore.newItem({id: 'test', otherfield: 'otherinfohere'});
myStore.save();
Supposedly the "newItem() was not passed an identity for the new item" error appears when you haven't provided an identifier for the new item, which i have.
The whole purpose of this (Just in case anyone can provide a good idea or has done something similar before) is that i want to create a data grid that shows info from a particular store. The problem is, that in that store all the items may not have the same structure. For instance:
I may have a store that looks like this
{identifier: 'id',
label: 'name',
items: [
{ id:'1', name:'Ecuador', capital:'Quito' },
{ id:'2', name:'Egypt', capital:'Cairo' },
{ id:'3', name:'El Salvador', capital:'San Salvador' , additionalField: 'otherinfohere'},
{ abbr:'gq', name:'Equatorial Guinea', capital:'Malabo', additionalField: 'otherinfohere'},
]}
This is possible because I'm the one constructing the store in a Spring Controller (I'm also using the Spring Framework) from information I have locally stored in a Berkeley DB. So what i need is a data grid with a dynamic layout because I don't want blank spaces to show in the view in the rows with lesser amount of fields, and i need to show all the info in the store at the same time, but i don't know how to do this.
I thought of doing it by creating a simple layout of only 1 field. In it I would load data from a store i create dynamically at runtime. The data in the store would be composed of HTML combined with the values coming from the original store so I could obtain something like this, which is inside an attribute of a JavaScript Object and let the browser parse it for me:
<div><span>id: originalID </span>....</div>
This of course is a simple example, the html layout i'm looking for is far more complicated, but i think that passing it as a string to an object might do the trick.
The problem is that i don't even know if that idea will work because i get that error whenever i try to add values to my secondary store.
rdb.modules.monitor.historicStore.fetch({onComplete: function(items, request){
for (var i = 0; i < items.length; i++){
var item = items[i];
var obj = new Object();
obj.id = rdb.modules.monitor.historicStore.getValue(item, "id");;
var html = "<div><span>";
html += rdb.modules.monitor.historicStore.getValue(item, "sql");
html += "</span></div>";
obj.html = html;
myStore.store.newItem(obj);
}
}});
In this context "historicStore" refers to the JSON store that has the values that i need to convert and add to "myStore" after i added some HTML.
I hope you got the main idea of what I'm trying to do. If anyone can help me we either of these problems i would really appreciate it. Thanks in advance
For the issue regarding store:-
"id" is mandatory for a store, if it is going to be used for a grid(datagrid, EnhancedGrid, etc. whatever). The items are handled only on basis of "id" attribute by the grid data structures.
Usually, id can be a loop variable/ auto incrementation, to avoid any cases like you have said. Before adding the store to the grid, ensure that all items have the id attribute. You can write a function which will loop through each item and check for this, else add an auto-incrementing value for the id attribute of that item.

Creating a drop down list in asp.net mvc3

I am working on Simple Web Application using asp.net MVC4
I wonder to know how to create a drop down list in asp.net mvc4
In my application , I don't wanna use "ID_Sous_Type " but I wanna load a list from "Sous_Type" class
http://i.stack.imgur.com/qf1C4.jpg
I wrote this code in my index method :
var GenreLst = new List<string>();
var GenreQry = from d in secdb.SousTypes
orderby d.ID_Sous_Type
select d.Nom_Sous_Type;
GenreLst.AddRange(GenreQry.Distinct());
ViewBag.types = new SelectList(GenreLst); //Can't load this
In my View :
#Html.DropDownList("types")
UPDATE !
I am working on a form to retrieve data and save it in my table
I have two tables , Task and TaskType
For Task , The creation page is being like that .
http://i.stack.imgur.com/qf1C4.jpg
For the last field "ID_Sous_Type" , I would like to load list (from other table TaskType) to give a good user interface where the user can choose an appropriate type in better way (giving ID_Sous_Type is not that understandable )
For that , I would like to load the names of (TaskType) in Dropdown List
In my index controller :
I created .
var GenreLst = new List();
//Here i got all the names from TaskType table
var GenreQry = from d in secdb.SousTypes
orderby d.ID_Sous_Type
select d.Nom_Sous_Type;
GenreLst.AddRange(GenreQry.Distinct());
Then I added Ranges to easily get it
but I couldn't "Bind" it in Dropdown list , I wonder to know HOW !!
If i understand correctly your ViewBag.types is missing some vital information and that's why it's returning your list. It should be something like :
ViewBag.GenreId = new SelectList(db.Genres, "GenreId","Name");
See this article on the official .net site it should help you understand dropdown lists better.
http://www.asp.net/mvc/tutorials/mvc-music-store/mvc-music-store-part-5

Categories

Resources