I am new in ASP.net MVC.
The website I am modifying has a drop-down list called "site", and users can change the site, then the rows of sales of the site would be shown accordingly.
Now my client wants the "site" drop-down list to include "All Sites", so when "All Sites" is selected, all sales across all sites would be shown.
Can someone give me a direction about what I should do?
Should I change table mapping to let every sale always point to an actual site and dummy site called "All Sites"?
Thanks
B
You can make a function with an optional parameter which will help us to decide whether we have to show sales of all sites or sales of only selected site.
The function will looks something like this:
public IEnumerable<Sale> GetSales(int? id)
{
if (id != null)
{
var salesBySite = getSalesBySite((int)id);
return salesBySite;
}
else
{
var salesOfAllSites = getAllSales();
return salesOfAllSites ;
}
}
In drop-down list all options should have values as the ids of respective site but the option "AllSites" should not have value or empty value.
When user select any site from dropdown, id will be passed to the function GetSales. If user select AllSites from dropdown then no id will be passed to function, function will return the sales of all sites.
In my opinion, there is no right way to do that. But it looks like a "report" to me. User is actually selecting a filter.
You shouldn't change the table, you can summarize on C# or create a view
Related
Hypothetical:
Say i'm having someone order a cake and they choose vanilla or chocolate, and then they have to choose a frosting
if vanilla: strawberry or buttercream
if chocolate: mocha, dark chocolate or buttercream.
Right now the frosting value in the data model can accept all four options, so all four show up in the dropdown.
a) is there a way to change the binding for the second dropdown after the first is chosen?
This can be done without having the data saved in any datasource. Simply do the following...
Suppose the first dropdown is named primaryDropdown and the second dropdown is called secondaryDropdown. In the primaryDropdown options set the following:
["Vanilla", "Chocolate"]
Also, make sure to uncheck the option allowNull and on the onAttach event handler, place the following:
widget.value = "Vanilla";
Now we move on to the secondaryDropdown. Here, we will do a binding so place the following in the options value:
getAvailableOpts(#widget.root.descendants.primaryDropdown.value)
In the client script, we need to make sure that function exists so please paste the following in any client script:
function getAvailableOpts(primaryValue){
var options;
switch(primaryValue){
case "Vanilla":
options =["Strawberry","Buttercream"];
break;
case "Chocolate":
options = ["Mocha","Dark Chocolate","Buttercream"];
break;
default:
options = [];
}
return options;
}
From here, you are good; However we can still make it better. For that, make sure to also uncheck the allowNull option for the secondaryDropdown and then we need to add some logic in the onValueChange event handler of the primaryDropdown.
widget.root.descendants.secondaryDropdown.value = widget.root.descendants.secondaryDropdown.options[0];
References:
https://developers.google.com/appmaker/ui/input-widgets#dropdown
https://developers.google.com/appmaker/ui/binding#bindings
https://developers.google.com/appmaker/scripting/client#use_scripts_in_binding_expressions
Im guessing you set the dropdown "possible value" options in the data source and you have those fields as just string fields in your table.
the quick and dirty way to do this is go to the Cake drop down and on the Property Editor>Events>OnValueChange select Custom Action and use this Code
if(widget.value==="Vanilla"){
widget.root.descendants.Field.options = ['Strawberry','Buttercream'];
}else if (widget.value === "Chocolate"){
widget.root.descendants.Field.options = ['Mocha','Dark Chocolate','Buttercream'];
}
"Field" here is replaced with the name of the dropdown box for your frostings
also go to the property editor of the frostings dropdown and delete everything in the options field there.
I was trying to solve for a similar situation and created an additional table to serve as a lookup.
I have a drop down for CATEGORY with possible options set on the field in the main data source.
Then I have a second table with 2 Columns: CATEGORY, and SUB_CATEGORY.
On the entry form I have options for the SUB_CATEGORY drop down set to SUB_CATEGORY on the CATEGORY_MATRIX lookup table.
Then for an onValueEdit event on the CATEOGRY drop down I have a script to reload the CATEGORY_MATRIX table source based on the value of the CATEGORY drop down in the query so when the CATEGORY is selected only valid SUB_CATEGORY options are shown in the second drop down.
var datasource = app.datasources.CATEGORY_MATRIX
datasource.query.filters.CATEGORY._equals = newValue;
datasource.load();
There may be more efficient ways to do this but the benefit is I could create another form page and dynamically add new combos so there isn't any required code change as new combos are needed.
See Datasource Paging Issue (Revised)
for the original question.
Markus, you were kind enough to help with out with the issue of incorporating a record count into a query using a calculated datasource. I have a search form with 15 widgets - a mix of date ranges, dropdowns, text values and ._contains, ._equals, ._greaterThanOrEquals, ._lessThanOrEquals, etc.
I have tested this extensively against mySQL SQL code and it works fine.
I have now added a 16th parameter PropertyNames, which is a list with binding #datasource.query.filters.Property.PropertyName._in and Options blank. The widget on the form is hidden because it is only used for additional filtering.
Logic such as the following is used, such that a particular logged-in user can only view their own properties. So if they perform a search and the Property is not specified we do:-
if (params.param_Property === null && canViewAllRecords === false) {
console.log(params.param_PropertyNames); // correct output
ds.filters.Property.PropertyName._in = params.param_PropertyNames;
}
The record count (records.length) is correct, and if I for loop through the array of records the record set is correct.
However, on the results page the table displays a larger resultset which omits the PropertyNames filter. So if I was to search on Status 'Open' (mySQL results 50) and then I add a single value ['Property Name London SW45'] for params.param_PropertyNames the record count is 6, the records array is 6 but the datasource display is 50. So the datasource is not filtering on the property array.
Initially I tried without adding the additional parameter and form widget and just using code such as
if (params.param_Property === null && canViewAllRecords === false) {
console.log(params.param_PropertyNames); // correct output
ds.filters.Property.PropertyName._in = properties; // an array of
properties to filter out
}
But this didn't work, hence the idea of adding a form widget and an additional parameter to the calculated recordcount datasource.
If I inspect at query.parameters then I see:-
"param_Status": "Open",
"param_PropertyNames": ["Property Name London SW45"],
If I inspect query.filters:-
name=param_Status, value=Open
name=param_PropertyNames, value=[]}]}
It looks as though the filter isn't set. Even hard coding
ds.filters.Property.PropertyName._in = ['Property Name London SW45'],
I get the same reuslt.
Have you got any idea what would be causing this issue and what I can do for a workaround ?
Using a server side solution I would suggest editing both your SQL datasource query script (server side) that is supposed to filter by this property list and including the same code in your server side script for your calculated Count datasource. The code would look something like this, not knowing your exact details:
var subquery = app.models.Directory.newQuery();
subquery.filters.PrimaryEmail._equals = Session.getActiveUser().getEmail();
subquery.prefetch.Property._add();
var results = subquery.run();
if(!results[0].CanViewAllRecords) {
query.filters.Property.PropertyName._in = results[0].Property.map(function(i) {return i.PropertyName;});
}
By adding this code you are filtering your directory by your current user and prefetching the Property relation table, then you set the filter only if your user canviewallRecords is false and use JS map function to create an array of the PropertyName field in the Property table. As I stated, your code may not be exactly the same depending on how you have to retrieve your user canviewallrecords property and then of course I don't know your relation between user and Property table either, is it one-to-many or other. But this should give you an idea how to implement this on server side.
I am developing a Web application which is based on ASP.NET 4.0, JQUERY, AJAX and Javascript. I have a particular search page in which a user can search via multiple factors i.e. either by Date, Name, Code, Category etc.
For e.g.
A) In a SearchProducts form, user can search a product via its unique Number OR Name OR Start Date/End Date OR Category OR etc etc.
B) User can search by either one or all of the parameters which a standard search form should be able to do.
C) If user searches via Start Date and End Date say 1st Dec 2012 to 31st Dec 2012 so for example my Search Results consist of 4 Products i.e. 4 products are purchased from 1st Dec to 31st Dec
D) Results are displayed in the grid and by clicking on the Product Number its redirecting to its View page (selected Product Specific full details) with ProductID via Query string.
E) I have a requirement which enables the user to retain search results which he/she has searched via Back To Search button in View page (selected Product Specific full details) page.
Now, What I have planned is as follows:
1) When a user submits on the Search then I want to store the refference of Search Paramters i.e Date, Name, Category etc which user has entered.
2) I will set a value in query string to differentiate normal request and request Via Back to Search button.
3) code in Search Page:
if (!(IsPostBack))
{
string tempRequestMode = string.Empty;
if (Request.QueryString["requestMode"] != null)
{
tempRequestMode = Request.QueryString["requestMode"].ToString();
if (tempRequestMode == "searchResults")
{
//RestoreValues();
//Fetch results from the database again based on above results
}
}
}
Now, My question is:
I wanted to use ASP.NET Cache for this purpose:
Advantages: its expiration and dependencies
Disadvantages: its has the application scope i.e. its not per user wise as Session is.
Second option is session:
Advantages: its per user wise.
Disadvantages: Session is more memory intensive.
I am confused that what Should I use. Is there any other option to use as Search Criteria is different for different users so want user wise maintenance of data.
You can write all search criteria to QueryString.
When a User clicks the Search Button, run this Javascript:
CLIENT-SIDE
<script type="text/javascript">
var url = "Invoices.aspx?type=__type__&status=__status__&order=__order__";
var type= $("#<%= drpType.ClientID%>").val(); // Type
var status = $("#<%= drpStatus.ClientID %>").val(); // Status Parameter
var order = $("#<%= drpOrder.ClientID %>").val(); // order Parameter
window.location = url.replace("__type__",type).replace("__status__",status).replace("__order__",order).replace(");
</script>
SERVER-SIDE
protected void Page_Load(object cart, EventArgs curt)
{
_type = Request.QueryString["type"];
if (string.IsNullOrEmpty(_type))
_type = Enums.InvoiceUserTypes.RS.ToString(); //Default
_status = Request.QueryString["status"];
if (string.IsNullOrEmpty(_status)) _status = "ALL"; //Default
_order= Request.QueryString["order"];
if (string.IsNullOrEmpty(_order)) _order = "date"; //Default
drpStatus.Value = _status;
drpType.Value = _type;
drpOrder.Value = _order;
RunReport();
}
When user click Back button . Search parameters will be on the URL
I think the best approach to this case is to redo the search using the stored filters once the user gets back to the search page. Any other approaches will bring you a big drawback.
Caches Expire and if you use the default implementation they won't allow your app to scale to multiple machines since they are local.
Using sessions is a bad idea too because they will eat your resources AND won't allow you to scale too.
If you must store the results you should store them serialized (LOB pattern) in a database or another network accessible resource so you could retrieve them in any application server.
I'm using an asp.net gridview to display a list of data from an mdb file. There are 5 columns displayed, with approximately 240 rows of data. Each row displays "first name", last name", "title", "genre", "issue", and "id".
Each "title" entry has corresponding .aspx page. There are approximately 180 actual .aspx pages that corresponds to the "title" entries in the grid.
An example of this relationship looks like: title = "Once upon a time in a long story"; and the aspx page might be /alongstory.aspx.
What I want to accomplish: Allow users to click the title field on the grid and open corresponding .aspx page.
What I've done so far: created a aspLabel on the "title" field - Text='<%#Eval("Title") %>'; and added C# code for label load event:
aspLabel l = sender as aspLabel;
l.ClientsideEvents.Click = String.Format("function(s,e) {{window.location = \"{0}"; }}, GetPageUrl(l));
And the GetPageUrl:
Private string GetPageUrl(aspLabel l)
{GridViewDataItemTemplateContainer c = l.NamingContainer as GridViewDataItemTemplateContainer:
var value = (string)DataBinder.Eval(c.DataItem, "Title");
string result;
switch (value) {
case "in the mirror":
result = "AnotherTitlePage.aspx";
break;
case "When your Eyes":
result = "AnotherTitlePage2.aspx";
break;
case "Her Delivery":
result = "ATitlePage1.aspx";
break;
case "You Never Know What You Might See":
result = "TitlePage3.aspx";
break;
default:
result = "TitlePageDoesNotHavesameNameAsDBEntry.aspx";
break;
}
return Page.ResolveUrl(result);
}
While this works, it requires all titles be hard coded into corresponding select statement along with the corrosponding url, which equates to 240 cases! Further, the only field which uniquely identifies each row is the "id" value, which in an integer - I've had a problem trying to set up a case select for int and return the proper url (casting error is the problem).
What I hope to accomplish:
Find the most efficient way to open the corrosponding url for the click on the "title" field of the grid view without hard coding both the field name from the grid column and the url into the case select.
So, given the information above, would a case select be the best approach for this requirement?
Any examples or suggestions of better approaches would be most appreciated!
Instead of making 180 actual .aspx pages, you must have to use concept of routing introduced in c# 4.0 and above.
here you can generate N number of pages dynamically and only one page will be work as template.
please refer below link for more details
URL Routing in asp.net as example www.jobdoor.in
In a customised form I would have a create Purchase Menubutton which opens a dialog to create a purchase order.
But I need to select few records like one or two lines and then create purchase order only for those records. How do I do that?
Take a look on the "Create purchase order" button on the SalesTable form.
It works differently: you select the lines to purchase after you press the button, but it might work in your case also.
Also have a look on how to use multiple selected records in a grid.
Here is a piece of code which allows you to get the record from the previous form.
You have to put this piece of code in the INIT method of the dialog. So you have to override the init of the dialog.
DmoVehicleTable vehicleTable;
DmoVehicleId vehId;
// Get the vehicle ID from the previous form
if (element.args() && element.args().record())
{
switch (element.args().record().TableId)
{
case (tableNum(DmoVehicleTable)):
vehicleTable = element.args().record();
vehId = vehicleTable.VehicleId;
break;
default:
throw error (strFmt("#SYS477", this.name()));
}
}
I hope this will help you.
If you need more help: http://sirprogrammer.blogspot.com/