I understand this may be an elementary question, but I'm new to Asp.net webforms, so please bear with me.
I have a lengthy form on a page that I would like to autosave when users type in a field, or make a selection. The problem is, all I've been able to find online is autosaves that work on a timer. I'd prefer that it saves as the user makes their edits. Also I would like just the individual form element being edited to be sent to the server to avoid sending the entire page back each time.
I've read that I should use a webservice to accomplish this, but since I want to autosave individual items and not the whole form on a timer, how would I set up a webservice to accomplish this? I'm new to webservices I'd like to know what to read up on. Any links are appreciated.
Also, how is the autosave functionality effected when using asp.net validation controls? I've looked around but can't tell if the entire page needs to be valid to make a trip to the server, or if just a single valid item can be sent itself.
Thanks for any help!
If you set AutoPostBack=True on the field, and you add an OnChange event for it (this will vary depending on the type of field the user is interacting with), you can execute a save. Don't call Page.Validate in the methods where you're doing these updates. Call it when you hit the Submit button.
This could cause a LOT of round trips to the server, and it's a lot of code to write and debug.
The Timer approach is one call to one method on a repetitive basis. If you can I'd recommend going with a timer, but sometimes that's not an option.
Generally speaking this is what you'll want to setup on the client-side. Ideally, you will end up with lots of tiny requests which do not require much power on the back-end. This however depends on lots of variables including the database engine you're using.
$(document).ready(function () {
$("input").blur(OnFieldChanged);
});
function OnFieldChanged()
{
var $this = $(this);
var isValid = ValidateField($this);
if (isValid)
{
SaveField($this);
}
}
function SaveField($field)
{
if ($this.val() === $this.prop("oldVal")) return;
var data = {
id: $("idfield").val()
};
data[$field.attr("id")] = $field.val();
$.post({..}).done(function() {
NotifySaved($this);
$this.prop("oldVal", $this.val());
});
}
function ValidateField($field)
{
// Validate the field with your method of choice, manually call Microsoft's client-side validate function or switch to jquery validate.
return true;
}
Related
I have a model which is in autosave mode. When the user clicks on a button below code is executed.
I want the status to change and get saved and then it should execute the refresh function as the refresh functionality is dependent on the status value. But with the below code refresh function is getting executed before the new status is getting saved.
widget.datasource.item.status='inside';
refreshPanelWithColor();
What I really want to do is this to have the callback functionality but I can't use the saveChanges as it's only for manual save mode.
widget.datasource.item.status='inside';
widget.datasource.saveChanges(function() {
refreshPanelWithColor();
});
How to achieve callback functionality here without switching to manual save mode?
As how Markus Explains in his comment, this functionality is not available at the moment. You can of course use another solution which is using server scripting and reloading the datasource item. In order to achieve that, your client script should look similar to this:
var recordKey = widget.datasource.item._key;
var status = "inside";
google.script.run.withSuccessHandler(function(){
widget.datasource.item._reload(function(){
refreshPanelWithColor();
});
}).withFailureHandler(function(err){
console.err(err.toString());
}).updateDesiredRecord(recordKey, status);
And of course, you need to implement your server script being called from the client. It should look something like this:
function updateDesiredRecord(recordKey, status){
var record = app.models.MYMODEL.getRecord(recordKey);
record.status = status;
app.saveRecords([record]);
}
I'm not sure what your refreshPanelWithColor() function does but I hope you get an idea of what this solution intends to.
You just have to bind your function to datasource on after save event.
In Meteor 0.7.0.1, is it possible to count/find out the all the queries that are currently listening to a particular Collection?
I am trying to create a function which does: Whenever the number of users listening on a particular query (eg: myCollection.find({color:'red'}) becomes non-zero, execute a function whenever documents are changed/added to a second Collection anotherCollection.
When/how is the find method called? If it's called when someone hits a button on the page, for instance, simply increase a serverside variable that will increase when that happens. To decrease this variable when the user leaves the page, listen to the window.onbeforeunload event and decrease the count when it happens.
Alternately, if you have a login system, assign a boolean value such as online to each user. When they log in, make their online status true with the following code. if(Meteor.user()){Meteor.user().online=true;}. Make sure an onbeforeunload sets their online status to false when they leave. Then, do something like Meteor.users.find({online:true}).size() to get the amount of users online.
Basically, rather than update when myCollection.find({color:'red'}) is called, put that in a function. For instance:
if(Meteor.isClient){
Session.set('browsing', false);
function findColor(c){//Alerts the server when the user attempts to get a color.
//This is presuming they don't use the plain MongoDB command.
//Your button/however you're finding the color should use this command
if(!Session.get('browsing'))//if it's already true, don't increase the count
{
Meteor.call('incBrowsing');
Session.set('browsing', true);
}
return myCollection.find({color:c});
}
window.onbeforeunload = function(){Meteor.call('decBrowsing');};
}
if(Meteor.isServer){
var browsing = 0;
Meteor.methods({
incBrowsing: function(){browsing++;},
decBrowsing: function(){browsing++;}
});
}
I haven't tested this, but I hope it works for you. You didn't provide too many details on your problem, so feel free to comment below if you or I need to clarify something.
I'm a very new ASP.NET developer (and web developer at all for that matter.) I want to put together a simple website that has the web server providing a form containing a few controls for setting a timer, and a start button, which when pressed, posts the configuration to the server (for how long the timer is set for.) and also starts the timer in the client, upon expiration, it would also post to the server that this has been done.
If this is easy please explain to me how to go about doing something like this, if this is not easy, or even more so if this is "not a good way to go about this" please explain to me a better architecture or design for this.
As this is a client-side thing, I wouldn't use ASP.NET :) Obviously it still stands for the server-side, anyway:
New ASP.NET MVC project with a single controller, two views, and two corresponding viewmodels.
View has a <form> with the timer <select> or text-box or something.
Controller has an action that receives the POSTed form data and saves it or something, then returns a 303 response to a view that has a hidden field that specifies when the timer should end, this value should be persisted on the server in Session state in case the user refreshes the page. The value should be saved as an absolute UTC date-time value.
The client has a simple client-script that, on page-load, inspects this hidden fields and sets up the timer using setTimeout.
The script also contains a callback function that will be called when the timer reaches its end. This callback function will create and populate a hidden dynamic <form> element which is submitted, causing a POST request to the server with some tag that identifies the client and timer that expired. The server then does another 303 redirect back to the original view, possibly containing a message for the user or something.
This is probably the simplist way using modern techniques and avoiding complexities inherent in using AJAX or external frameworks like jQuery or Mootools. Note my use of 303 redirect instead of returning a HTML repsonse to a POST request - this is for the user's benefit so they never get the browser "Resubmit form?" dialog and also prevents the timer from being reset.
UPDATE:
Why 3xx Responses Are Good:
When a client submits a POST request, the webserver can respond either by returning a response directly, or by doing a 3xx redirect to another page. The problem with providing a response directly is that the content of the response (i.e. the web page) is not "accessible" as far as HTTP is concerned: you cannot retrieve the same content with a GET request. This is why when a user presses F5 or hits Refresh for a POST'd page they get a message-box prompting them (in cryptic language) to resubmit the form, however often if the user resubmits the form they'll end up breaking the application because their data will be processed twice. This is why ASP.NET WebForms, which its heavy reliance on "postback" is being phased out.
Javascript
The code would look something like this:
// bind to this event rather than executing directly because the onload event is only fired after the entire DOM is available. If you run the code immediately then you won't be able to traverse the DOM tree.
window.onload = setUpCallback;
function setUpCallback() {
var hiddenField = document.getElementByID("someHiddenFieldId");
var timeStampEnd = parseInt( hiddenField.value ); // this is the number of miliseconds since 1970-Jan-01 00:00
var timeStampNow = new Date().getTime(); // this also returns a miliseconds-since-1970 value
var timeToEnd = timeStampEnd - timeStampNow;
if( timeToEnd > 0 ) {
window.setTimeout( onTimerEnd, timeToEnd ); // set-up the callback
}
}
function onTimerEnd() {
var form = document.createElement("form");
form.action = "http://mywebsite/uriToSubmitPostTo";
form.method = "post";
document.documentElement.appendChild( form );
var clientField = document.createElement("input");
clientField.type = "hidden";
clientField.name = "someFieldName";
clientField.value = "someValueToIdentifyTheClientOrJustUseSession?";
form.appendChild( clientField );
form.submit();
}
I am developing an application in GWT as my Bachelor's Thesis and I am fairly new to this. I have researched asynchronous callbacks on the internet. What I want to do is this: I want to handle the login of a user and display different data if they are an admin or a plain user.
My call looks like this:
serverCall.isAdmin(new AsyncCallback<Boolean>() {
public void onFailure(Throwable caught) {
//display error
}
public void onSuccess(Boolean admin) {
if (!admin){
//do something
}
else{
//do something else
}
}
});
Now, the code examples I have seen handle the data in the //do something// part directly. We discussed this with the person who is supervising me and I had the idea that I could fire an event upon success and when this event is fired load the page accordingly. Is this a good idea? Or should I stick with loading everything in the inner function? What confuses me about async callbacks is the fact that I can only use final variables inside the onSuccess function so I would rather not handle things in there - insight would be appreciated.
Thanks!
Since the inner-class/ anonymous function it is generated at runtime it needs a static memory reference to the variables it accesses. Putting final to a variable makes its memory address static, putting it to a safe memory region. The same happens if you reference a class field.
Its just standard java why you can only use Final variables inside an inner-class. Here is a great discussion discussing this topic.
When I use the AsyncCallback I do exactly what you suggested, I fire an event though GWT's EventBus. This allows several different parts of my application to respond when a user does log in.
I have an Asp.net page which requires certain sections to be partially updated automatically at an interval of 5 seconds.
I was planning to use the good old Timer control with the AJAX Update Panel for this purpose, but after a bit of reading on this control i found out that it may have some problems especially if,
1) The time difference between the async event performed ( 4 seconds ) by the update panel and the Timer's tick interval ( which is 5 seconds ) are quite small, the update panel will be held up in the async operation all the time.
2) Also, the fact that timer control doesn't work very well with Firefox.
I just wanted to get your opinion as to whether if i should go ahead with the timer and update panel approach, write some custom javascript that does the partial page update or some other strategy altogether.
Personally, I tend to think that the DIY approach is better -- easier to debug and easier to write.
You can use a javascript setInterval for a timer, and every time the function is called, you can initiate an ajax request to your asp.net code-behind to fetch whatever data needs to be updated.
For example, let's say you simply need to, every 5 seconds, update the current time on a page. Let's assume you have a span of ID currentTime on your page, something like:
<asp:Label id="CurrentTime" runat="server" CSSClass="currentTimeLabel" />
In your initial PageLoad event, you set the time:
protected void PageLoad(...)
{
CurrentTime.Text = DateTime.Now.ToString();
}
Now you need to define some javascript on your page that will, every 5 seconds, call the code-behind and get the new date/time value.
Doing this with something like jQuery is very simple:
$(document).ready(function() {
setInterval(5000, updateTime);
});
function updateTime() {
url: "myPage.aspx/SomePageMethod",
success: function(data) {
$(".currentTimeLabel").text(data);
});
}
In ASP.NET, getting the PageMethod to work is the trickiest part (for me, anyway). You need to create a public function in your code-behind with a 'WebMethod' attribute. Something like this:
[WebMethod]
public static string GetCurrentTime()
{
return DateTime.Now.ToSTring();
}
I didn't test any of this code, but the basic premise is sound and should work fine.
Now, this may seem more complicated than using an UpdatePanel, but I find it easier when I know what code is actually running on my page.
If you need to update a series of controls instead of just one control, you can use a more complicated web method that returns xml or json data, and then parse that using javascript.