Auto refresh label in MVC View - javascript

I have an auto refresh method (something like below) in my controller. In which I will update data in ViewBag, which I use in label of view. But I'm unable to refresh my label automatically. Please help me.
var waitHandle = new AutoResetEvent(false);
ThreadPool.RegisterWaitForSingleObject(waitHandle,(state, timeout) =>
{
// my viewbag
viewbag.time = DateTime.Now.TimeOfDay;
viewbag=date
}, null, TimeSpan.FromSeconds(5), false);

MVC doesn't work like WebForms (where reassigning a value populates to the UI). You'll need to write a separate action (or WebAPI method) and use AJAX/JavaScript to pull updates. (Alternatively you could use SignalR, but that may be overkill).
Also, if this is a recurring event, you may want to look into a library like Quartz.NET to perform the action. Then, post updates to a shared resource (looks like you're storing timestamp of last execution). From there, use setInterval/AJAX on the client to retrieve and display that value.

Related

Trying to load data into a new view

I have an issue attempting to create a "clone" of data on a page. The summary is that I have a create customer jobs screen and a separate manage customer jobs screen. These both work fine. I have a need to "clone" already existing customer job data to create a new similar set of jobs. So in my management screen, I have a clone button. I want this to head off to my "create" page with the data pre-populated with the original data, minus one or two pertinent identifying pieces of information, e.g. Job Name.
My issue is I cannot seem to get the post to redirect off to the Create page with my new data in the view model. I can't have a submit action as this saves the data; the data I'm cloning won't be persisted between the manage and create screens.
Here is where I'm at:
In my CSHTML:
<button type="button" name="btnClone" value="btnClone" id="btnClone" formaction="CloneJob" class="btn btn-primary" style="width: 150px;">Clone</button>
This fires off a click event to grab the current jobId which then fires off this function:
function CloneJob(jobId) {
$.post('CloneJob', { JobId: jobId }, function (data) {
window.document(data);
});
}
In my controller, I have this:
[HttpPost]
public ActionResult CloneJob(Guid jobId) {
// logic which wipes off the old data job from the view model
// eg names, ids, etc. but leaves the actual job details intact
return View("CreateJob", manageJobViewModel);
From this, I can see the HTML being returned in the IE/Chrome debug network section, but it won't go off to my CreateJob view populated with the data.
What am I missing?
First, if you're going to replace the entire tab/window contents, don't use AJAX. There's no point, and it's just something extra to maintain. Utilize a standard link, instead. Second, a POST should only be made when something is changing. This here should just be a simple GET request.
Create a link to the "create" URL and pass an id for the job that's being cloned. In the create action, then, you can look up that job from the database, based on that id, populate your view model with the data, and return it with the view.
If you want the appearance of a button, you can just style the link to look like a button, but you should use a standard old <a> tag, because that's the semantic meaning here.
I have managed to get further in that it now "works". My controller is unchanged, but my javascript is now:
$.when($.get('CloneJob', {jobId: jobId}))
.then(function (response)
{ $("body").html(response); });
I'm aware that this is still ajax, but in the face of an alternative that is more technically acceptable, this does work. Would be happy to take any advaces for a more technically neater approach as I understand that this is a bit of a misuse of ajax.
I have managed to get this cracked.
My cshtml now contains this code:
#Html.ActionLink("Clone Job", "CloneJob", null, new { #class = "btn btn-default", #style = "width: 150px" })
My controller just grabs the current viewmodel from the session and uses it to clone the job. Then, the controller now simply returns the view with the new model I set up within the method.
return View("CreateJob", clonedJobViewModel);
It's simple now when I look at it, but it's the getting there part.

Backbone.model.save(): POST(create) / PUT(update) logic doesn't match application logic - how to avoid PUT in certain situations?

I'm creating an Web-Application (Frontend and Backend, so both are under my control) using Backbone and Pyramid, being connected via a RESTful API.
During development I encountered a problem several times by now, where Backbone PUTs (=updates) a new model, while it actually should POST (=create) it.
Backbone decides whether to POST or UPDATE a model depending of the presence of an ID-field (if no ID present in the current model: -> POST/create | if so: PUT/update).
However I encountered several situations by now, where this behaviour doesn't match my application logic.
Let's say our main model (and its objects being persistently saved in a relational database in the backend) is called Foo, having fields like id, field_1, field_2.
Example #1: Creating a template or preview of Foo: Before creating (=POSTing) an object of Foo, I can create and show a preview to the user and/or save it as a template.
While doing so, the backend (in case of the preview: temporarily) adds the object to the database and returns the full model - including an ID in its HTTP response - back to Backbone.
Template- and Preview-objects of Foo are (temporarily) saved into the same table, as final objects (column type indicates its type (0 = final/live, 1 = preview, 2 = template)).
When now - after previewing / saving as template - trying to actually CREATE an object of Foo, the Backbone model already has the ID field set and actually PUTs and updates the template or not-anymore-existing preview, instead of POSTing and therewith creating a new Foo inside the database (as intended).
=> solution #1: calling POST /json/preview does not return the ID field, so Backbone doesn't get confused.
=> solution #2: overriding parse() of Foo in Backbone-model to kick out ID field from response
.=> kinda works
Example #2: Having a Periodic model, which refers to a Foo-template. Intention of a Periodic is to offer the user the possibility of semi-automatically creating a new Foo object based on a Foo-template every X months.
Now there is a call GET /json/periodics, which returns all Periodic-objects with its nested Foo-objects (Foo-templates), including their IDs, e.g. [{'interval': 12, template_id: 42, template: { 'id': 42, field_1: 'foo', field_2: 'bar', .. } , { .. } , .. ].
On the frontend the user now can periodically confirm (or skip) creating a new Foo-object, by issuing: periodics[X].template.save() which however again PUTs and therewith updates the Foo-model, instead of POSTing and creating a new one (as intended).
Here again (as in example 1), I could strip out the ID field of Foo - either in the backend or frontend.
However there are situations, where I need the id-field of templates, e.g. when actually editing them, so here I'd need two calls (GET /json/templates_WITHOUT_FOO-IDs and GET /json/templates_WITH_FOO-IDs). which also sounds far from right.
Question is: What's the right (and consistent) way of avoiding Backbone falsely assuming a model should be PUT instead of POSTed in certain situations / views?
Backbone's save and fetch methods just make calls to the Backbone.sync
method, which in turn is just a wrapper for an ajax call. you can pass
in ajax parameters using the save function without having to actually
extend it. basically ends up being something like this:
model.save({attributes you want to save}, {type:'POST', url: 'apiurl/model/:id/played'});
You would have to do this every time though so it is probably better practice to extend Backbone.sync for your model.
The Backbone website has a bit of information about what I'm talking about as far as the Backbone sync and save taking ajax options. There are also a few examples I've seen on extending sync but I can't seem to track them down at the moment.

GridX clear the sort without making new request

I am using GridX to display data, but I often change the data store that the GridX is using. I do this by using grid.setStore() and pass in a Dojo JsonStore (this is asynchronous data of course). I do not recreate the grid every time I change the data store, just call setStore(), then refresh().
The grid also has the NestedSort module activated. My problem is this:
If the user sorts on a store, and then chooses a set of different data to look at, the code calls:
grid.sort.clear();
grid.setStore( /* new store*/ );
grid.refresh();
Without .clear() being called, the grid will try to sort the new store of data (which is usually invalid, and throws a 500).
With .clear(), the store will make a call to the server to sort the first data store, before then calling for a fresh batch of the next data store.
Ideally I want to tell the grid to clear any sort preference before I grab the next set of data, so that it is not attempting to sort it. I do not want it to make an additional call to sort the first data immediately before it gets replaced.
I finally worked it out. To clear the sort information in the grid you must modify the grid model. The sorting in the grid model can be done using this:
grid.model.sort();

How to use $watch to see changes when updating a database record

I'm having nightmares on how to display on the UI what I have changed in my database. I have this scenario that I need to select certain titles and then I will click a button that will change its status.
Problem is when I select titles and then I click the change status button it don't automatically reflect on the UI. Here is my update function.
$scope.updateTitleStatus = function(statusId, cp){
ContentAssessmentService.updateSelectedTitles($scope.selectedTitles, statusId);
$scope.selAll = !$scope.selAll;
$scope.selectedTitles = [];
};
Here is my service.
this.updateSelectedTitles = function(selectedTitle, statusId){
var self = this;
_.forEach(selectedTitle, function(selectedTitle){
ContentAssessmentFactory.updateSelectedTitleStatus(selectedTitle.id, statusId);
});
};
Here is my array which is the selected title stored.
$scope.selectedTitles = [];
Can you tell me how to use $watch function? I don't know how to do it. I've done this but it doesn't work.
$scope.$watch(function($scope){
return $scope.selectedTitles;
}, function(newValue) {
$scope.selectedTitles = newValue;
console.log(newValue);
});
I just need to update the UI immediately without refreshing the page (that's my last option but trying not to) when I have click the change status button.
You are going to have to use polling or a websocket connection. $watch does not "watch" your database. It watches #scope variables that are usually bound to the view and reacts to changes there. It sounds like you are looking for something more like meteor.js that keeps an open websocket and will dynamically update the view when the database is changed from another client, background process etc. These are completely different things. To achieve this sort of behavior with angular, the easiest approach would be to poll your api incrementally and update models in angular when the api gives you modified data.

YUI Datatable - call arbitrary function *once* on sort

We're using a lot of YUI data tables to display data, and rather than using the built-in pagination we've done our own so we can paginate on the server side using AJAX without downloading the whole data set (which is often huge).
Whenever we use the data table's sorting funcionality, though, it will only sort the one page because from YUI's point of view that's the entire data set.
I need to be able to call an arbitrary function to reload the page data whenever the user tries to sort the data. I've looked into DataTable's sortFunction parameter and it's not ideal because it gets called multiple times (once for each row combination it needs) and I need to do it just once.
There are probably plenty of hacky ways I could do this, but what's the "nicest" way of going about this?
Ideally, you would sort on the server side.
when create the datatable, one of the config options is generateRequest (see this example: http://developer.yahoo.com/yui/examples/datatable/dt_bhm.html )
generateRequest is a meant to be a function which generates a URL which returns the correct data set with which to fill the table. You probably have this.
For me, whenever I click on the column header (to sort), it makes a new request to the server, getting the correct page of sorted data.
Why not write a custom function and close over a variable that tracks whether it's been called?
var hasBeenCalled = false;
function mySortFunction(){
if(!hasBeenCalled){
// do something
hasBeenCalled = true;
}
}
Then replace the sortFunction with that.

Categories

Resources