Update Gridx with JsonStore, on event? - datagrid

I am new to Web UI, Dojo, Java etc. If you are referring any advance topic please give some reading reference. It will help.
Context:
I have Gridx design using JsonStore, which takes a target + id for URL. With fixed "id" Grid loads well.
I have Dynamic Tree. It is working fine with lazy-loading etc.
Objective:
Based on click (or dblclick) event for a given node in Tree, I have to load Gridx with data. Hence, if tree node "id":7 is clicked, then JsonStore: /target/7 should be fetched and get loaded in Gridx.
Issues:
As you can guess, at start there is no valid "id" property to fill in JsonStore. In click event handler of tree, I will get this value, upon a user click. Hence, can't call gridx.startup() in "ready". Though I have "placed" the widget in "ready".
Hence, I have following snippet to handle,
<
// this function is called from tree event handler
function LatestTabGridxLoad( id ) {
console.log( "ID %s fetched.", id );
LatestTabGridxStore.idProperty = id;
LatestTabGridx.startup();
LatestTabGridx.body.refresh();
}
ready(function()
{
TabLatestAssetTree.startup();
LatestTabGridx.placeAt( "ReportMiddleTabLatestCenterContainer" );
}
Now, trouble is, at first time loading, JsonStore GET fired with /target/ alone, without any "id" without any user click. Hence, server responds with 405. Subsequently, when user clicks, again same HTTP GET without "id" results in HTTP 405. I am not able to somehow feed "id" to the GET URL. I have checked JSON, it is in perfect shape, as it works in standalone table, that is declarative(ly) defined.
Please suggest me ways to link a TREE node through its "id" to Gridx. Also suggest, if approach I am taking is right way to solve this problem.

Sorry, misunderstanding of the question. I thought it was about gridx tree but it is about regular gridx controlled by another widget.
The problem is in this line:
console.log( "ID %s fetched.", id );
LatestTabGridxStore.idProperty = id;
'idProperty' is the name of the JSON attribute which stores the ID. This will not change with each selection. If it is not set, JsonStore will assume it to be 'id'. What you intended to do was to modify the target property of the store to include the ID. This can done directly and will look something like the following (details are application specific)
LatestTabGridxStore.target = (someURL) + '/' + id;
After that, the content of gridx needs to be replaced using the new store setting. There are few ways to do it, the simplest being destroying the current gridx instance and replacing it with another one which uses the altered store.

Related

Send Data from Fragment to Main Activity through NavGraph

In my app, I'm using a Single Activity with multiple Fragments Architecture and I navigate between them using the Navigation Library. Within one of the fragments, I have multiple categories, each associated with an ID. When a category is clicked, I take the user to that respective category explainer screen with the code below.
val directions = MainNavGraphDirections.launchFragmentWithThisCategoryId(categoryId!!)
onRoute(AppRoute.Directions(directions))
The above code sends them to the explainer screen associated with the associated categoryId. All is well until this point, the right explainer screen gets launched based on the categoryId. Within this explainer screen, I have a deep-link with a tag chatbot://fragment/wizardintro that is supposed to let the main activity know the specific follow-up fragment to send the user to. I denote all the fragments that can receive this deep-link with the code below.
companion object{
const val DEEP_LINK = "chatbot://fragment/wizardintro"
}
In the MainActivity, I have a method that receives all the different deep linking intents and matches them to the tags that will launch the respective category fragment with the code below.
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
intent?.data?.toString().also { deepLink ->
when (deepLink) {
IntroductionFragment.DEEP_LINK ->{
val categoryId = intent?.getLongExtra("categoryId", 0L)
val directions = MainNavGraphDirections.actionGlobalGoalWizard(categoryId)
navController.popBackStack()
navController.navigate(directions)
}
}
Now my problem arises when I try to retrieve this categoryId in the Main Activity and pass it to the next fragment. I don't get anything and only the default Long gets passed along. I think the function override fun onNewIntent(intent: Intent?) { } in the MainActivity recieve any intent. To be clear, these intents are sent from the explainer fragment which is technically a fragment that loads a json. Within the json there is a "route": {"type": "route", "url": "chatbot:///fragment/wizardintro"
In the MainActivity, the onNewIntent functions receive these intents unpacks them with this line intent?.data?.toString().also ...then in the when statement picks a fragment that has a matching chatbot:///fragment/wizardintro
I said all this to say that the main activity doesn't actually gets the categoryId, it simply picks launching the neccessary fragment without actually having anything associated with the categoryId
This makes me think that the first clicked categoryId doesn't actually get passed to the MainActivity. Although, to me, this seems like it shouldn't be this hard to pass objects/data from a fragment to an activity. What am I missing? What can I read to educate myself more on this?
Thanks for your time and responses!
Since we already got to the conclusion that MainActivity is not getting categoryId, you just need to pass that categoryId with the deep-link.
However, there is no need for any communication from Fragment to Activity.
You could achieve the same result through communication only between Fragment to Fragment, and Activity to Fragment.
What you want to do is to look more closely on deep-links and android navigation in the AndroidDocs, click here.
As you can tell, there are different ways to go around this, starting with arguments for each fragment. Assigning categoryId as an argument to the Fragment would help you use the navigationController and navigate to the new Fragment, while passing the categoryId to it.
Now, I am aware that you also wish to launch it with a deep-link; there's also a good explanation on here. According to the docs, you can place arguments in deep-links in the following manner...
Placeholders in the form of {placeholder_name} match one or more characters. For example, http://www.example.com/users/{id} matches http://www.example.com/users/4. The Navigation component attempts to parse the placeholder values into appropriate types by matching placeholder names to the defined arguments that are defined for the deep link destination. If no argument with the same name is defined, a default String type is used for the argument value.
The navigation is something amazing and capable, you just need to be aware of everything it can actually do. You can even bind it to a BottomNavBar, with extremely minimal amount of code.
Try going over the AndroidDocs about it, and it'll grow on you for sure.

Getting selections from a list object

I have a table inside of appmaker that I've added checkboxes to like so:
I'd like to get a list of the emails from entires that the user checks. At this point I'm not even able to access the status of a single checkbox. This is the current code snippet I tried adding to a button:
console.log(widget.parent.parent.parent.children.Panel1.children.Table3Panel.children.Table3.children.Table3Body.children.Table3Row.children.UserSelectionCheckbox.value);
I get the error:
Cannot read property 'children' of undefined
at Home.Panel1.OuSelectPanel1.Button6.onClick:1:133
I was able to use the autofill to write this entire statement, why can't it find the child object? Is there any way to reference this list directly without going down the tree from the widget or the app root?
For this type of functionality the autofill (intellisense) will not work for you. You need to address the children differently when you try to get a collection of rows from a table. I would suggest code similar to this for your button onClick event:
var rows = widget.root.descendants.Table3Body.children._values;
var emails = [];
for (var i in rows) {
var value = rows[i].children.Checkbox1.value;
if (value) {
emails.push(rows[i].datasource.item.Email);
}
}
console.log(emails);
Again the auto complete code feature simply won't work after you choose the _values, which will return all immediate children of your table body, which is what you want.
based on the 1:133 it seems to be saying that Table3Row has no children. I wonder if using widget.root.descendants.Table3Row might be a different way of doing it address the particular table.

Google Tag Manager - Parse Dynamic Data Layer Variable

I want to parse a 'pushed' data layer string. I intend to use it to track click events and setup the appropiate funnels in Google Analytics, it looks as follows: products.view.19|view recent product|19
The first part (products.view.19) is the unique page identifier.
The second part (view recent product) is the action.
The last part is (19) is the action identifier, this way actions may be grouped and compared more easily.
So I did the following, I first created a trigger (it fires when a link has the tag 'data-trackclick' in it) which pushes the data value to a variable (variable for datalayer). However, now I want to split that variable in to 3 new variables, as described above. I selected 'javascript macro' for this but somehow it returns 'undefined'. The macro looks as follows:
function() {
var data = {{TrackClickData}};
var pieces = data.split('|');
if (pieces[0].length()) {
return pieces[0];
} else {
return data;
}
}
Obviously this didnt work since it would only run on the initial load and not (like I thought) when the macro was requested, so it should somehow be fired on the 'click' and then set the variables accordingly.
Is this possible to do? Or do I really have to add the dataLayer.push() in script tags?
A few things:
.length() is wrong, the property for array length is .length without the ()
if it exists, pieces[0] is not an array, then .length would return the string length, see How do you check for an empty string in JavaScript? for more standard way of checking for empty strings
Is this possible to do? There's virtually nothing you can't do with GTM, since you can write JavaScript code, you can do whathever you code allows you to do, and splitting a string to use parts of it as variables is certainly within the realm of possibilities.
My advise is to make your code work outside GTM first (eg test it in the browser console), then once it's all working, port it to GTM.

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. :)

Why does $find(strSomeOtherRadAjaxPanel) return null?

Problem context:
1) rcbComboBoxInRadPanel is a Telerik RadComboBox.
2) rcbComboBoxInRadPanel has "OnClientSelectedIndexChange" event which fires "itemSelected."
3) rcbComboBoxInRadPanel is contained a radAjaxPanel called "foo."
4) strSomeOtherRadAjaxPanel names a RadAjaxPanel that exists outside of "foo."
5) $find(strSomeOtherRadAjaxPanel) returns a valid RadAjaxPanel if executed alone.
function itemSelected(rcbComboBoxInRadPanel)
{
var strComboBoxInRadPanel = rcbComboBoxInRadPanel.get_id();
var intRecordID = rcbComboBoxInRadPanel.get_value();
$find(strSomeOtherRadAjaxPanel).ajaxRequest(intRecordID);
}
It appears that $find(strSomeOtherRadAjaxPanel) always returns null when called from the "OnClientSelectedIndexChange" event of rcbComboBoxInRadPanel.
Is there another way for me obtain a valid reference to the RadAjaxPanel using $find(strSomeOtherRadAjaxPanel)?
Any help you can offer would be helpful.
Can you obtain reference to the strSomeOtherAjaxPanel from other client handler of the combo or when it is moved outside of its ajax panel holder? If the strSomeOtherAjaxPanel is initialized properly on the client, it should be available in each of these cases.
check your rendered html source code. ASP dynamically generates clientID names so your server side IDs may not have persisted. They probably now look something like ctl100aFMLksdjflFML
Either target them some other way (like class name, jQuery search, etc) or set the client ID mode to static (if it is the only instance of this object) then try again.

Resources