How to force load and item by key in form? - datasource

The case
1 - I have an accordion widget with datasource Tasks.
2. - I have a form to display info on a selected Task. It has a datasource TaskByKey.
The sought solution:
There is a button on both Tasks AccordionRow.
onClick the button should, based on the Key of the item of the AccordionRow load its data in the form with datasource TaskByKey.
What I tried:
I tried implementing the solution given as an example in Google's template, Project Tracker:
/**
* Navigates user to the specific project view page.
* #param {!string} projectKey - project key to view.
* #param {boolean=} forceReplace - optional flag that forces to replace URL
* state in cases when state push would be normally used.
*/
function gotoViewProjectPageByKey(projectKey, forceReplace) {
var params = {
projectKey: projectKey
};
gotoViewProjectPageByParams(params, forceReplace);
}
Of course the above example targets a page, where as I want to change the datasource of an element on the same page.
TLDR
How can I set the onClick event of a button to load an item by key from datasource_X to datasource_X_byKey?

Considering the fact that your TaskByKey pretends to filter only a specific task... you can put the following on the onClick event of the button.
var taskKey = widget.datasource.item._key;
var ds = app.datasources.TaskByKey;
ds.query.filters._key._equals = taskKey;
ds.load();
//Then, here you either navigate to a page or open a dialog or open a popup.
The above will work considering that your Tasks datasource and your TaskByKey datasource come from the same model.
Reference: https://developers.google.com/appmaker/scripting/api/client#Query

Related

Get SelectedItem in Dropdownlist without FormMethod.Post

I have a dropdownlist that is bound to a list in my model. Model.list_IDs
The current page is an "editing" page where a user would inherently change a property of the model by using the dropdownlist.
#Html.DropDownListFor(model => Model.ID, Model.list_IDs, new { style = "width:250px" })
The items within the dropdownlist are not intuitive, so I would like to provide a button, that when clicked, retrieves additional information via a stored procedure (called from the controller via a method called GetDetails)
The button is created through an action link, and I plan to display a partial view (like a focused pop up window) that shows the additional information once the button is clicked.
#Html.ActionLink(" ", "GetDetails", new { id = Model.ID.ToString() }, new { #class = "lnkMagnify16", title = "View Details" })
Obviously Model.ID.ToString() is incorrect, because it will only send the model's current ID, rather than the ID currently selected in the dropdownlist.
How can I change Model.ID.ToString() to represent the dropdownlist's current selected item?
I know there is a way to do this using FormMethod.Post (Get selected item in DropDownList ASP.NET MVC) but I do not want to reload the page with a submit button. I'd also like to avoid "third party" approaches like JavaScript if possible.
JavaScript is not a "third party" approach, and it's also the only way to accomplish what you want here. Whether by a standard form post or via AJAX (JavaScript), you must make a new request to the server to get the new information you want.
Now, since all you're specifically after is a way to dynamically update the the Model.ID value in the link, you can do that without AJAX or a form post, but you still must use JavaScript, since all dynamic behavior client-side originates from JavaScript. Basically, you'd need to bind to the change event of the dropdown and alter the href property of your link.
document.getElementById('ID').addEventListener('change', function () {
var selectedId = this.options[this.selectedIndex].value;
document.getElementById('AwesomeLink').href = // alter `href` with `selectedId`
});
However, that link is still going to change the whole view if the user clicks it. If you truly want the user to stay on the page, then you'll need to fetch the response of that link using AJAX and then either add it to the page somehow, whether that be directly or via a modal popup (which will required yet even further JavaScript to achieve). Also, it's not clear how the Model.ID value ends up in the URL, i.e. whether it's part of the path (/some/url/{id}/) or as a query string param (/some/url/?id={id}). If it's the former, I'd recommend switching to the latter, as it will make it much easier to build your URL client-side.
var xhr = new XMLHttpRequest();
xhr.addEventListener("load", function (response) {
// add response.responseText to the DOM
});
xhr.open("GET", "/some/url/?id=" + selectedId);
xhr.send();

Modifying column header names in Master-Detail grid in Devexpress

I have a Master-Detail set up with 2 grids. On the master grid, I have the ShowOnlyPredefinedDetails option set to false.
This means that I see a little + sign that allows me to expand the details of the detail grid (in the master grid). I would like to rename
some columns in that section as well as hide certain columns. I'm using VB.NET How do I go about this. See image.
You can accomplish this by using the grid control ViewRegistered event, from there you can modify the columns in that grid view that have columns within them that you want to modify, rename, or remove. Here is an example, I hope that it helps:
private void myGridControl_ViewRegistered(object sender, DevExpress.XtraGrid.ViewOperationEventArgs e)
{
if (e != null)
{
if (e.View != null)
{
//Inside of this statement you can adjust, add, and modify all of the columns inside of that grid that appears when you click on the +
(e.View as GridView).Columns["myHiddenColumn"].Visible = false;
(e.View as GridView).Columns.Add(new GridColumn() { Name = "AddColumn", Caption = "Name To Display", Visible = true, FieldName = "DataField"});
(e.View as GridView).Columns["DataField"].OptionsColumn.AllowEdit = false;
(e.View as GridView).Columns["DataField"].OptionsColumn.AllowFocus = false;
(e.View as GridView).Columns["DataField"].OptionsColumn.ReadOnly = true;
}
}
}
I think all you need to do is create a second grid view for your details. If you haven't already done this, do the following:
In your grid designer, click "Retrieve Details" if you have not already done so. This will cause the designer to recognize that you have a second level in your bound object:
Once you see the second layer, now you need a new grid view for it. Click on "Click here to change view" and select "Create a new view" and pick "GridView."
Now you will see both grid views from the designer, and clicking on one or the other will change the context of the menus to the left:
For example, if you have gridView2 selected, when you click on the "Layout" menu, it will show the current layout for your detail grid rather than the master grid. From here, you can remove or add columns as you see fit. Likewise, from the "Columns" menu you will see the new columns (you may have to add them to the view by dragging them over), and you can change the Caption property to change the text of the title.
I suggest you use the Data Annotation attributes with properties of your data-classes to declare how you data should be displayed in GridControl:
To skip column generation for the specific property you can mark this property with the <DisplayAttribute(AutoGenerateField := false)> declaration.
To prevent column from displaying you can mark this property with the <DisplayAttribute(Order := -1)> declaration. Later, user can show this column via Column Chooser UI.
To specify the column caption use the <DisplayAttribute(Name := "YOUR CAPTION")> declaration.
You can also control filtering/editing/formatting and validation capabilities.
Related Links:
Tutorial: Create and Manage Data in Code and Apply Data Annotation Attributes
Video Tutorial: Create and Manage Data in Code and Apply Data Annotation Attributes

Dojo:how to find if the widget has focus in dojo

how do I find out if my custom widget has focus in Dojo?
i have dojo editor i wnat to know if the editor has already focus or not?
you can use the module dijit/focus to find out the focus
FROM DOJO DOCS
Tracking active widgets
At any point in time there is a set of (for lack of a better word)
“active” or “focused” widgets, meaning the currently focused widget
and that widget’s ancestors. “Ancestor” can mean either DOM ancestor
(ex: TextBox –> Form), or a logical parent-child relationship (ex:
TooltipDialog –> DropDownButton).
For example, if focus is on a TextBox inside a TabContainer inside a
TooltipDialog triggered by a DropDownButton, the stack would be
TextBox –> ContentPane –> TabContainer –> TooltipDialog –>
DropDownButton.
The activeStack[] parameter indicates this set of widgets, and an app
can monitor changes to activeStack[] by:
require([ "dijit/focus" ], function(focusUtil){
focusUtil.watch("activeStack", function(name, oldValue, newValue){
console.log("Focused widget + ancestors: ", newValue.join(", "));
});
});
the question in title has a different answer than the one in the descriptions.
there are two ways achieving the question in the title, by using dojo's focusUtil ("dijit/focus"). both ways give you something that you could find the widget using it and the dijit's registry ("dijit/registry").
focusUtil.curNode: gives you the DOM Node that currently has the focus. the function below, you could get the widget reference.
function getWidgetByNode(node){
var result;
while (!result && node){
result = registry.byNode(node);
if (node.parentElement)
node = node.parentElement;
else
node = null;
}
return result;
}
var focusedWidget = getWidgetByNode(focusUtil.curNode)
focusUtil.activeStack: gives you an array of the widgets (parent to child) that has the focus. so the last item in the array is the direct widget which has the focus. index values are widget ids, so you should get the widget by the following code
var focusedWidgetId = focusUtil.activeStack[focusUtil.activeStack.length-1];
var focusedWidget = registry.byId(focusedWidgetId);
now if you want to know if the currently focused widget is some specific one, it depends on what you have in hands from that specific widget:
widget itself: like the return values of above samples. now you have to compare if these are the same thing. you can not compare two widget objects using the == operator. you could compare their ids like this:
myWidget.id == focusedWidget.id
widget's id: this way you just easily get the id of the current node from focusUtil and compare it with the id you have liek this:
myWidgetId == focusedWidgetId
references:
http://dojotoolkit.org/reference-guide/1.9/dijit/focus.html
http://dojotoolkit.org/reference-guide/1.9/dijit/registry.html
require([ "dijit/focus" ], function(focusUtil){
var activeElement = focusUtil.curNode; // returns null if there is no focused element
});
check blow url here you can see some examples
http://dojotoolkit.org/reference-guide/1.8/dijit/focus.html#dijit-focus
a) For dojo 1.6: call dijit.getFocus(). This will return an object containing the currently focused dom node, among other things (selected text, etc.). To get the corresponding widget, simply do:
var activeElement = dijit.getEnclosingWidget(dijit.getFocus().node);
This is the full reference for dijit.getFocus(), from the source code:
// summary:
// Called as getFocus(), this returns an Object showing the current focus
// and selected text.
//
// Called as getFocus(widget), where widget is a (widget representing) a button
// that was just pressed, it returns where focus was before that button
// was pressed. (Pressing the button may have either shifted focus to the button,
// or removed focus altogether.) In this case the selected text is not returned,
// since it can't be accurately determined.
//
// menu: dijit._Widget or {domNode: DomNode} structure
// The button that was just pressed. If focus has disappeared or moved
// to this button, returns the previous focus. In this case the bookmark
// information is already lost, and null is returned.
//
// openedForWindow:
// iframe in which menu was opened
//
// returns:
// A handle to restore focus/selection, to be passed to `dijit.focus`.
b) For dojo 1.7 and up, use dijit/focus:
require([ "dijit/focus" ], function(focusUtil) {
var activeElement = focusUtil.curNode; // returns null if there is no focused element
});

Dynamic menu button items in TinyMCE

I have a custom menubutton in my tinyMCE editor that uses specific HTML elements elsewhere on the page as the menu items. I use a jQuery selector to get the list of elements and then add one each as a menu item:
c.onRenderMenu.add(function(c,m) {
m.add({ title: 'Pick One:', 'class': 'mceMenuItemTitle' }).setDisabled(1);
$('span[data-menuitem]').each(function() {
var val = $(this).html();
m.add({
title: $(this).attr("data-menuitem"),
onclick: function () { tinyMCE.activeEditor.execCommand('mceInsertContent', false, val) }
});
});
});
My problem is that this only happens once when the button is first clicked and the menu is first rendered. The HTML elements on the current page will change occasionally based on user clicks and some AJAX, so I need this selector code to run each time the menu is rendered to make sure the menu is fully up-to-date. Is that possible?
Failing that, is it possible to dynamically update the control from the end of my AJAX call elsewhere in the page? I'm not sure how to access the menu item and to update it. Something using tinyMCE.activeEditor.controlManager...?
Thanks!
I found a solution to this problem, though I'm not sure it's the best path.
It doesn't look like I can make tinyMCE re-render the menu, so instead I've added some code at the end of my AJAX call: after it has updated the DOM then it manually updates the tinymce drop menu.
The menu object is accessible using:
tinyMCE.activeEditor.controlManager.get('editor_mybutton_menu')
where mybutton is the name of my custom control. My quick-and-dirty solution is to call removeAll() on this menu object (to remove all the current menu items) and then to re-execute my selector code to find the matching elements in the (new) DOM and to add the menu items back based on the new state.
It seems to work just fine, though tweaks & ideas are always welcome!

DojoX Mobile ListItem load HTML via AJAX and then remove from DOM

Let's say in a view I have a DojoX Mobile ListItem that is pulling an HTML view fragment into the DOM via AJAX and then transitioning to that view. Assume this is all working fine.
Now, I go back to the initial view that had that ListItem on it and click some other button that destroys that view node from the DOM. If I now click on that ListItem that previously loaded that view node into the DOM (which has now been removed), it will try to transition to a view that doesn't exist. It doesn't know that it has been removed.
Is there some type of way to tell a ListItem that it needs to fetch the HTML again because what was previously fetched no longer exists? I am not seeing anything about doing this in any documentation anywhere. I don't think a code sample is really necessary here, but I can provide a minimal one if necessary.
I went a different route and left the view exist in the DOM, and simply made a function that clears all sensitive data out of the view.
Okay, in this case, i guess you could hook the onShow function of your ListItem container(or any other onchange event). Create a listener for said handle to evaluate if your item needs reloading. Following is under the assumtion that it is the item.onclick contents showing - and not the label of your item which contains these informations
Or better yet, do all this during initialization so that your ListItem container will be an extended with custom onClick code.
Seems simple but may introduce some quirks, where/when/if you programatically change to this item, however here goes:
function checkItem() {
// figure out if DOM is present and if it should be
if( isLoggedIn() ) {
this.getChildren().forEach(function(listitem) {
if( dojo.query("#ID_TO_LOOK_FOR", listitem.domNode).length == 0 ) {
// this references the listItem, refresh contents.
// Note: this expects the listitem to be stateful, have no testing environment at time being but it should be
listitem.set("url", listitem.url);
}
});
}
}
Preferably, set this in your construct of the container for your ListItems
var listItemParent = new dojox.mobile.RoundRectList({
onShow : checkItem,
...
});
Or create listener
var listItemParent = dijit.byId('itemRegistryId');
// override onClick - calling inheritance chain once done
dojo.connect(listItemParent, "onClick", listItemParent, checkItem);