AngularDart NgComponent using event listeners in the controller - dart

I have an NgComponent in Angular Dart which instantiates a search box and according to the query strings it populates another div in my html template with the ng-repeat directive.
More precisely,
Query string update: there is a binding to the input text value with a field in my components' controller.
Results population: In the attach() method I added a watcher for the local field which acts as a model to the input box, and whenever it changes I add to a local list some items which then acts as a model to the ng-repeat directive in another div.
So far everything works fine. But now I want to add some event listeners inside my component, like keystroke listeners or if possible to add listeners on specific elements in my html template. I have used CSS for hover and focus events and also ng-focus and ng-blur for easy functions. But I do not think that this can be used for keystroke listeners.
The reason I want the keystroke listener is to enable results traversing using the arrow keys. While the cursor is inside the input text box I would like to move to the first result, which is in another div, with the press of Down arrow, and then continue to the other results.
Thank you

OK, It seems that I have finally found the solution.
The solution is to implement the NgShadowRootAware interface with my component and then inside the void onShadowRoot(ShadowRoot shadowRoot) method I have full access to the DOM created inside the shadow dom template.

Related

How to create a custom ul element with polymer dart which fires on-added and on-remove event when children are added?

I have been making a simple todo list as a way to learn polymer dart.
Here is my todo example.
I have limited experience in web-programming in general. My idea is to create a simple app with
One text input
2 Custom ul elements (New task ul and Done task ul)
Entering a string in text input and pressing enter creates a li item which is added to New task.
Deleting an element from New task results in addition of element to Done task.
Now I know creating a separate model and tracking the changes in an observable list seperate from html might be better approach. But as a learning exercise I would like to create a custom ul which fires a on-added and on-removed event when li item are added and removed from it respectively.
Now I have a couple of questions.
Why is there no on-added or on-remove event in ul (html)? I would like to understand what is the rational behind it.
How would one go about creating a custom UListElement which fires on-added and on-removed event when li items are added or removed from it respectively?
Because normally you won't need it. As you wrote you change the model and let Polymer update the view.
You can easily implement it yourself by overriding the attached/detached methods and fire an event.
See https://stackoverflow.com/a/22424213/217408 for how to fire custom events in Polymer.dart.
Gunter is right. You're thinking is a little old school, so I'm surprised to hear that you're new to web dev. With Polymer, you need to embrace the data-driven view model. You want to be watching the backing model properties that are driving your view, not the DOM. Something like this:
#observable List<Task> tasks;
void tasksChanged(oldValue) {
// react to changes
}

Orchard CMS conditionally hide widget and suppress zone

I am trying to conditionally suppress a widget from its driver. I basically have logic that if met, should display the widget and if not, should suppress it. The widget loads properties from the current page content item, and based on some properties should display or hide. I've got all the logic working, the only part left is suppressing the actual output.
I've tried returning null from the driver, however this simply outputs an empty widget (with its wrapper). How do I completely remove the widget from view?
Finally, the zone that this widget is placed in should suppress if none of the conditional widgets display.
Is this type of flexibility possible in Orchard? Preferably from my custom module not my theme, I'm trying to separate functionality from styling.
EDIT:
Here is the context of my situation and what I am trying to accomplish. I'm sure there is a much cleaner way to do this within Orchard than how I have naively designed it the first go-around: My client's copywriters tag pages as they see fit (using the Tags module/part). I have created 2 custom content types, "Testimonials" and "Offers", both with tags themselves among other properties [these are managed by a different team of copywriters].
On most "inner pages" of the website (I'm using a layer to determine the appropriate pages), the page's sidebar gets a "Testimonial" widget and a "Offer" widget. These widgets both operate the same, although independently of each other:
They grab the tags of the current page, then pull a random [Testimonial|Offer] that has any matching tags as well. There are 4 cases that can happen given any inner page: a testimonial is displayed and the offer is hidden (testimonial tag matched, offer tag didn't), the testimonial is hidden and the offer is displayed, both the testimonial and offer displays, and finally neither displays. The first 3 use cases are working great, the 4th is what I'm having difficulty with, as the sidebar [zone] still displays even if both widgets do not (returning null from their respective drivers).
A bit of context about widgets: widgets are supposed to be pieces of contents that are visible on some or all pages of the site, and that provide information that is not directly related to the main content item on the page (if there is such a thing).
As a consequence, what you are describing should not be implemented as widgets (all that you had to do to make it work attests to that further), because they are really part of the content item. Instead, you should have implemented a part or a field. You can then simply place the shape for this part of field, using placement, by specifying a top-level zone: <place the_shape_name="/the_zone_where_you_want_it:1"/>
Unfortunately I've had to use a bit of a hack so that I could move on with the project as I'm under an aggressive deadline, but if there is a better method and/or solution I'll test as I get the chance and mark as the answer.
To get it to work, I overwrote the Widget.Wrapper.cshtml file within my theme. There, I assigned a variable to the Display(Model.Child) call, and if the result is an empty string simply return. This removes any empty widget wrapping tags. (I personally feel Orchard should behave this way by default):
var child = Display(Model.Child);
// -- NOTE: shape tracing breaks this logic!
if (string.IsNullOrWhiteSpace(child.ToString())) {
return;
}
Then simply replace the #Display(Model.Child) between the header and footer with #(child)
I then added the following method to my Layout.cshtml file.
Func<dynamic, IHtmlString> CollapsableZone = x =>
{
var display = Display(x);
string zoneName = x.ZoneName;
if (string.Equals(display.ToString(), string.Format("<div class=\"zone zone-{0}\"></div>", zoneName.HtmlClassify()), StringComparison.CurrentCultureIgnoreCase))
{
return new HtmlString(string.Empty);
}
return display;
};
Simple function that assigns the display call to a variable, checks if it is an empty zone tag, and returns. I then create variables for each zone assigned to the value of the function above. I replace all the #if (Model.ZoneName != null) with #if (!string.IsNullOrWhiteSpace(zoneVariable)), and replace the calls to #Zone(Model.ZoneName) with #(zoneVariable).
This is working for the time being. It is quite a hack and brittle solution but I've had to move on to other things.

Custom Component in JSF2 which takes input modifies it on button click and re-renders the component

I'm pretty new to JSF (Just 1 week old) and developing first component. Component is something like a table which takes a collection as input and renders the contents in a table format. In addition to that renders a "Remove" link at the end of each row.
I created "Composite" component (.xhtml) and ComponentType (a java class with #FacesComponent).
I got the complete table rendering and "Remove" link is displayed in each row. Now trying to add with action that is defined in my class with #FacesComponent.
<a4j:commandLink action="#{cc.removeRow(rowKey)}" value="Remove"/>
In my component (java class) I have this method removeRow(Integer rowKey) defined. But on clicking this "Remove" link the action is not triggered. I have "h:form" also defined in the component.
Any help or pointers is much appreciated.
EDITED: just looked at this question How to implement a dynamic list with a JSF 2.0 Composite Component? and it resembles almost my requirement. Just one thing I'm not sure is what would be the form action when it is rendered and if I click the button in the component, how it would call the method inside its own component bean.
Ok, this is the mistake I was doing.
I'm rendering a custom table using Guava "Table" Collection. This initialization of table happens in "encodeBegin" which was called once. So when I clicked on submit it was trying to re-render the table and it sees everything as null and hence throws NPE.
I now extracted the initialization of table to a separate method and a helper method to retrieve existing table if it's not null or re-initialize from the attributes.
It works now.

Detect if JQuery Mobile came from a select dialog

I have a jquery mobile app that has a page. This page has three DIVs, I programmatically choose one of these DIVs based on a variety of variables. Regardless, the one DIV contains a select element. This element has 20 items in it. Because of the shear quantity, the select box opens in its own dialog. I'm fine with that, however, after a user makes a choice, the pagebeforeshow event of my hosting page is fired again. My problem is, I can't seem to figure out how to detect that this event was fired as a result of the user choosing an option or closing the select dialog.
Is there a way to detect in the pagebeforeshow event how we got here?
jQuery mobile passes meta-data to the callback functions of most events. From the docs on pagebeforehow:
Triggered on the "toPage" we are transitioning to, before the actual transition animation is kicked off. Callbacks for this event will recieve a data object as their 2nd arg. This data object has the following properties on it:
prevPage (object) - A jQuery collection object that contains the page DOM element that we are transitioning away from. Note that this collection is empty when the first page is transitioned in during application startup.
You should be able to use this in your callback function to branch to your advantage, i.e. detect if prevPage is the current page. This might look like:
$('#yourPage').live('pagebeforeshow', function(event, data) {
var from = data.prevPage;
// do some inspection of `from` and branch accordingly
// might require some experimental console.logging first
});
I also didn't verify the question raised in above comment, but data.prevPage has a copy of the entire previous page's HTML, accessed via data.prevPage[0].innerHTML. I'm sure you could do something like binding to the click event on the select dialog and tell it to add a class or whatever to the DOM where the user selected whatever entry, and scrape that back out of the HTML? Just throwing an idea out there.

How do you pass all the contents of a ListBoxFor?

I am currently binding an IEnumerable collection to a ListBoxFor, which works as expected, sending the currently selected values on POST. However, I need to send all the values instead (essentially any value in a given ListBoxFor I consider to be required, whether selected or not). How would I go about doing this?
(I can probably rig something up in jQuery where, on-submit, it manually selects all the elements in a box, but was wondering if there was a better way.)
If you want to continue using normal browser form serialization on submit, write a javascript function to fire right before the submission (hook into an onclick event or something) which iterates through the list box control and concatenates the desired values (perhaps comma-delimited) and places it in a hidden field. The value of that hidden field will be submitted normally and you can parse the individual values from it on the server side. It's still some manual work, but you avoid messing with GUI state (i.e. selecting all desired list box items) which I agree is something you don't want to do.

Resources