Buttons to load different Datasources to a Panel on a different Page - google-app-maker

Seems simple enough, but...
I have a Page (a dashboard) with buttons, one button for each Program. I have a different page with Tasks in a Table.
I want to load the Tasks page with the tasks for that Program from that programs button on the dashboard Page.
I've attempted multiple angles using Relations, queries and scripts from multiple tutorials and templates I get all the parts working but not working together.
This is how I think it should work.
On the dashboard Page each button calls its own script like:
currentProgram = "ALL";
function btnProgram1_click() {
currentProgram = "Program1";
app.showPage(app.pages.Tasks);
}
Then on the Tasks Page > Panel > Event > onAttach calls:
function loadTasks(){
if(currentProgram == "Program1"){
app.datasources.qryProgram1Tasks.load();
}
if(currentProgram == "Program2"){
app.datasources.qryProgram2Tasks.load();
}
}
I have SQL Datasources on the Tasks model like qryProgram1Tasks with a query expression for "Program1" and they return data as expected.
Seems to me this is what is not working as wanted to load, or replace and refresh a designated datasource to the panel app.datasources.qryProgram1Tasks.load();

Related

In Meteor, is there a way to detect when data is fully loaded to the browser?

This problem probably has been asked before, but I cannot seem to figure out an easy way to do it.
I have a Meteor page that shows messages posted by users in chronological order (newest message at the bottom). I want the page to:
#1) Subscribe to the messages (using publish/subscribe) based on a parameter supplied in the URL
#2) Render the page
#3) Display the messages on the page
#4) Scroll to the bottom.
There's no apparent way to know when 1, 2, and 3 are complete before initiating the scroll to bottom. Meteor does have an observe/added function to do an event when new messages are added to a subscription, however that's only when documents are insertted into Mongo, and it does not trigger when displaying results to the initial subscription.
I'll show code for the steps above:
#1: Subscribe to the messages using publish/subscribe: in /client/messages.js
Template.messages.created = function() {
this.autorun( function() {
this.subscription = Meteor.subscribe("messages", Router.current().params.category);
}.bind(this));
};
#2 Render the page, in /client/messages.html
<template name="messages">
{{#each messages}}
{{messageText}}<br><br>
{{/each}}
</template>
#3: Display the mssages on the page: /client/messages.js
Template.messages.helpers({
messages: function() {
var category = Router.current().params.category;
return Messages.find({category: category}, { sort: { messageDate: 1 } });
},
});
All this works, but does not automatically scroll to the bottom.
I cannot add a jquery scroll command to the Meteor onRendered section because it runs BEFORE the data is written to the DOM. I can do a Meteor.setTimeout to wait 1 second before scrolling to the bottom, but does not work if it takes longer than a second to fill the DOM with subscribed data.
Here's another thing complicating the matter. I am supplying the category variable in the URL. When the client selects another category, using Meteor/Blaze pathFor,
{{pathFor 'messages' channelid='new'}}
the browser does not reload/rerender the page, it simply updates the URL parameter which triggers the autorun to change what messages it has subscribed to. It simply writes the new data to the DOM. Because of this, I cannot to a jquery $(document).ready to detect whether the page is ready (because the page is always ready), and I cannot use some fancy handlebars thing like {{scrollToBottom}} at the end of my {{#each}} in messages.html because that it not re-run.
So, is there a simple way to detect when Meteor/Blaze completely finishes writing new data to the browser?
If I understand correctly, you really just want to know when all of your data is published from the server to the client (so you can then do something, in this case, scroll to the bottom).
All calls to Meteor.subscribe() return a subscription handle. This has a ready() method, that tells you all the data has been sent. This includes those done at a template level (which you might want to consider if appropriate for your use-case). More information here:
http://docs.meteor.com/#/full/Blaze-TemplateInstance-subscribe
There are several ways to use this - you need to decide what is appropriate for you. As ready() is reactive, you can just use this. However, you might find it easier to implement an onReady callback within your subscription (see documentation above).
I suspect you will need to implement an autorun within your template rendered. This is to avoid the reverse scenario where the data arrives before the rendering (and so the callback fires too early). Something like this should do the trick (noting you have already set your subscription handle in your template creation function to this.subscription):
Template.messages.onRendered(function() {
var self = this;
this.autorun(function(computation) {
if(self.subscription.ready()){
$(document).scrollTop($(document).height());
computation.stop()
}
});
});
This should ensure both that the function is only called after rendering and the data from the subscription is complete. The autorun is also stopped after executing the scroll to stop continued calling should new documents cause ready() to no longer be truthy (and then become ready again) - which might surprise people with the page re-scrolling to the bottom!

how to store a varibale value after page loading

In my application there is the multiple tab concept is there. i.e i have 1st page then "next button" to move to second page, then in 2nd page 2 button(prev,next). Thus when user click prev button i need to get the fields filled in 1st page. this can be achived using state management. If is there any way except this?
You can use sessions, example of which
in your 1st page:
string str;
Session["someName"] = str;
in your 2nd page you can retrieve by calling the session, because sessoin is a GLOBAL VARIABLE,
string n_str;
n_str = Session["someName"] as string;
I think it all depends on how your project is built, so you've many options:
1- You could build it as a single page with multiple tabs (as HTML Divs) and the "next" and "prev" buttons show and hide these Divs, so you don't need to store the data anywhere as the page didn't change (just show and hide).
2- Store it in a global variable like "Session"
but if you've a high traffic application you may run out of memory or you'll need to use in database session instead of the default in memory session storage.
3- Save the data partially (when moving from step to step) by using a web service or from code behind to the database and then reload it again when clicking prev.
As for me I recommend the first approach as it doesn't add extra load on the servers and don't affect the performance.

Lightswitch HTML databinding to a details collection

I have a simple master/details relationship where one order can have multiple revenue allocations. The order has a collection that contains these.
I want to sum a property in my revenue allocation objects and ensure that it adds up to my order total. However, if I databind on the count property of the allocations collection this gets called when you first add an empty object and not when that object has been populated. So an empty allocation is added at the time the "Add allocation" screen is created and the databind function called. That of course means that when the save button on the "Add allocation" screen is clicked, the databind function isn't called again.
Anyone got any ideas? I basically want my databind function to be called when the save button is clicked in the "add screen" and not before.
This is the HTML client - NOT Silverlight
I'm pretty sure that the solution would be to use an OData query to get your aggregate data within the databinding function of the save button - or perhaps a separate button (e.g. "Tally Order Totals"). Exactly how you do that? A bit too hard for me to answer right now, but start with a new button TallyOrderTotals and a new data field for your total. Edit the post_render event for TallyOrderTotals and lookup the allocations in the javascript in which you data bind the value of the new data field.
Somewhere you will need a piece of code that looks something like this:
myapp.activeDataWorkSpace.<datasource>.RevenueAllocations
.filter("OrderID eq " + msls._toODataString(<orderID>, ":String"))
.execute()
.then(function (result) {
// assign the result somewhere
}
I'm not saying that's something you can cut-and-paste - but definitely look at the msls.js documentation and see what you can do with querying your data inside the event context.
One quick point however - if you only need to calculate that total as a verification step, consider doing it in the SaveExecuting() event on the server side. This will allow you to throw an exception back up the tree to your HTML page which the msls.js script should render on the client side.
Hope that helps. :)

Meteor: display data - slow client, fast server?

Edit - Solved
My meteor app is used about about 20 people my office. Basically it's a glorified to-do-list. Managers add projects, and then adds tasks for each project, and then assigns them to employees. Employees see a list of the tasks assigned to them.
When a manager posts a new task, it takes a very long time to show up in their own task-list, but shows up near instantaneously for other people (employers or other managers).
A manager's project template looks something like:
HTML File:
<template name="project">
<input type="button" class="create-task" value="New">
{{#each tasks}}
{{> task}}
{{/each}}
</template>
app.js File:
var createTask = function (projectID) {
### a bunch of code that I don't think is relevant to the problem
### tasks are fairly complicated but it shouldn't matter
Tasks.insert({projectID: projectID})
}
if (Meteor.isClient) {
Template.project.tasks = function () {
return Tasks.find({projectID: this._id})
};
Template.project.events = {
'click .create-task': function () {
createTask(this._id)
}
}
}
When a manager creates a task, it rerenders the entire tasklist, and it takes about 2 seconds per-task. (tasks are fairly complicated and I need to streamline them, but that's another story). Other employees (and other managers) looking at the same tasklist have the new task appear in about 2 seconds. But for the manager, it takes 10-30 seconds to rerender all of the existing tasks, and it locks up the webpage in the meantime.
I assume I want to somehow insert documents on the server side instead of the client? Is there a proper way to do that?
Edit: (Some additional information - this is somewhat simplified but I believe contains all the relevant pieces)
There are three collections, which are essentially in a hierarchy - Projects, Tasks, and Comments.
Projects contain {name, create_date}
Tasks contain {projectID, name, description, create_date}
Comments contain {projectID, taskID, author, text, create_date, status}
Comment statuses can be "new", "finished", or "approved".
The database is not that large, and displaying all the raw data takes a few seconds. What takes a while is displaying a lot of conditional information. Depending on whether comments are new/approved/finished, they change color and/or are hidden from view.
Managers see a list of projects, and next to each Project, the number of "new", "finished", and "approved" comments associated with that Project. This is generated by something like:
Template.projectMenuItem.newCommentsLength = function () {
return Comments.find({projectID: this._id, status="new"}).count()
}
Tasks are also shown in a list view, that shows the number of new/finished/approved comments.
There are some other conditional display items. End result is that displaying a Task, even if the list form (without also displaying comments), it ends up taking about 2 seconds for each task template to render. If I remove the conditional-display-items, it renders near instantly.
EDIT - SOLVED: I moved the "createTask" function under "Meteor.methods" in the server code, and then called it from the client. Now adding a new task takes 2 seconds instead of 20-30. I'm still not sure why creating the document client-side was causing it to re-render all the tasks but it seemed like something that should be run server side anyway.

Populate data asynchronously from WebService in few dynamically created Div in ASP.NET?

Problem Summary:
I have one page having a textbox and a button.
On Clicking button it read few XMLs and get the following data.
Gets the list of database connectors to connect. A, B, C
Gets the list of queries linked to each connector. A[0,1,2], B[0], c[0, 1, 2, 4]
Now iterate though each database connector, connect, run each query, fetch data, create dynamic controls and panels and display in this fashion.
---A----
Gridview A[0] results
Gridview A[1] results
Gridview A[2] results
---B---
Gridview B[0] results
It works and displays properly if I try synchronously, connecting the connectors one by one. The page freezes for few seconds, but at the end when all operation is complete it displays properly. Problem happens when any of the connector is down. Example. If A is down then till we get the connector Timeout message, B and C also wait and page loading time increases.
Now there is a business demand that this should run Asynchronously, that means all the connectors should be connected and queried simultaneously like parallel. I tried to implement this by using WebService. But in vain. The Div created and closes and then the grid/data is populating. Since the divs are creating dynamically I have no clue how to place the gridviews in those divs.
My current logic is:
Loop through Connectors {
Create <Div class="Container">
Create <Div class="conLabel">Label</div>
Loop through Queries for this connector {
WebSevice _WS = new WebService();
__WS.GetDataCompleted += new GetDataCompletedEventHandler(__WS_GetDataCompleted);
__WS.GetDataAsync(Parameters Here);
}
Create </Div>
}
void __WS_GetDataCompleted(object sender, GetDataCompletedEventArgs e) {
Get result here from e.Result
Create New gridview and bind to it.
}
It displays like this.
---A----
---B---
Gridview A[0] results
Gridview A[1] results
Gridview A[2] results
Gridview B[0] results
I am not sure if this is the right approach or not. I am very new to WebService. How do i create a gridview in some div which itself is created dynamically.
Can someone help me finding any other approach to solve this problem.
I solved this by adding a ASP.NET Panel instead of creating dynamic literal control as .
Loop through Connectors {
Panel myPanel = new Panel();
myPanel.ID = "UNIQUEID"; // Using this ID i am identifying the container
Loop through Queries for this connector {
WebSevice _WS = new WebService();
__WS.GetDataCompleted += new GetDataCompletedEventHandler(__WS_GetDataCompleted);
__WS.GetDataAsync(Parameters Here);
}
}

Resources