Pass element refrence to self from DOM back to view model - html

Known feature:
<div #element (click)="myMethod(element)"></div>
this passes the div back to the VM for manipulation, etc.
What I'm looking for is short hand to pass an element to a method without declaring a template variable. It could look like this:
<div (click)="myMethod($self)"></div>
This would be helpful in cases where creating elements in an ngFor stops you from giving every element a variable name or in cases where using a third party library that sends its own $event and the element ref is missing. Does anyone know of any way to do this?

Related

Polymer two-way data binding and Facebook callback

I am very new to JavaScript and Polymer. I do like the PWA concept but now hit some roadblocks.
I tried to use polymerfire <firebase-auth> and was able to do google provider logins. But got blocked as I don't know how to do Facebook provider login and didn't find anywhere on how to use the tag as I wish to provide Facebook login too in JavaScript. If someone guides me to a source that works I will then not need part 2 of the question.
So, I tried facebook login via Graph API FB.login(). FB.login() has callback and I was not able to extract the response.name, public_profile and set it to Polymer attribute say {{user}} like
var userName = response.name; and then this.user = {displayName : userName};
I noticed that as soon as I exit FB.login() callback on successful login, I lose the changes done in assignment in callback to 'this.user ' object.
My question is - I am not able to make two way binding work in polymer. How can I change the object in child element and then it propagates to all the pages / polymer elements?
How can I change the object in child element and then it propagates to all the pages / polymer elements?
Well really that depends on how you set up all the pages. If you're in the parent, you can pass functions, variables, and objects to the child element by passing it in the component.
<ChildElement details={{_details}}/> // If you want to pass a details object to the child
<ChildElement sqft={{square(size)}}/> // This will call the square function inside your ChildElement and pass in the parameter size
Use the latter to call a function in your child and that function will have access to all the elements within that scope.
If you're in the child and you want to change something in the parent, you can do a callback with this.fire(someFunction()), and then create a function in your parent that with the same name. It's not too bad when you're just passing from parent to child or vice versa but if you're passing it everywhere, then you might want to look into some sort of state management. Passing things from one place to everywhere else will get ugly real fast.

Internal Links in Polymer 2.0

What is the correct way to implement internal linking in Polymer 2.0 (linking within the same page)? I cannot seem to get access to my components that are buried within ShadowDoms, so the traditional way of using link to top and <a name="my_section"></a> and <a id="my_section"></a> does not work.
I have also tried the solutions here to no avail:
How to query elements within shadow DOM from outside in Dart?
Is it possible to access Shadow DOM elements through the parent document?
Using querySelector to find nested elements inside a Polymer template returns null
The following code that I've tried all return null, even when I add an id to my component:
document.querySelector('#my_section'); //null
this.$.my_section; //null
this.root.querySelector('#my_section'); //null
this.shadowRoot.querySelector('#my_section'); //null
Perhaps there is a way to accomplish this using <app-route>?
I'm quite new to Polymer so any advice would be appreciated. Thanks in advance.
Please share more detailed code that which elements you want to access and manuplate. Here at this document
https://www.polymer-project.org/2.0/docs/devguide/dom-template
under the Static node map head shows shortly :
The this.$ hash is created when the shadow DOM is initialized. In the
ready callback, you must call super.ready() before accessing this.$.

Is there a way to have two custom elements sharing a DOM element, e.g. an <iron-ajax>

I have two custom elements having similar functionality and both having an <iron-ajax> element(in local DOM template) to make service calls, I was trying to extract these common part into a behavior. But I also realize that polymer behavior does not carry local DOM template. Is there a way to let the behavior have the <iron-ajax>? dynamically create it using Document.create?
As "behavior" is the Polymer way of doing code sharing, can a DOM element be shared across elements?
You should create an other element for your API calls which have inside the <iron-ajax> and have your api call methods, then you need just change the iron-ajax element in your elements and use your <api-element> for this.
Below are two methods which i can think of
Create iron-ajax element at root level of your application and then refer to that element from each of your element using querySelector or getElementById on document
In your behavior create iron-ajax element from javascript with createElement function of javascript.
In both the cases you can add event listener on response and error.

Polymer, how to wait for core-ajax to finish before rendering other elements?

Update: here are the docs for this situation: Conditional templates use the if attribute to conditionally create a template instance.
this app, plnkr.co, should do the following:
use core-ajax component to get project_location from DB(JSON in this example)
use google-map component to display the map with marker
when user drags the market, use core-ajax to save the new location to DB
Q: How to make google-map component to wait with it's rendering until AJAX request is finished?
Currently this error is appearing:
"Exception caught during observer callback: TypeError: latitude must be a number", and I assume that is because google-map is rendered before {{project_location}} is initiated.
<core-ajax id="ajax_get_location"
auto
url="project_location.json"
params='{"idProject":"{{idProject}}"}'
on-core-response="{{locationLoaded}}"
handleAs="json"
response = "{{project_location}}"></core-ajax>
<google-map id="project_location_map"
zoom="{{project_location.location_map_zoom}}"
fitToMarkers>
<google-map-marker
latitude ="{{project_location.location_map_marker_latitude | toFixed(2)}}"
longitude ="{{project_location.location_map_marker_longitude | toFixed(2)}}"
title ="{{project_title}}"
draggable ="true"
>
{{project_title}}
</google-map-marker></google-map>
I think the cleanest approach is not to think about this as a timing issue with <core-ajax>. Fundamentally, the problem is that you don't want to include the <google-map> element on your page until there's a value for project_location. In your snippet, the project_location value comes from <core-ajax>, but you could easily imagine a different implementation in which project_location is populated via some other means.
So, if you think about it that way, what would make sense is to wrap the <google-map> in a conditional template that checks for a value of project_location:
<template if="{{project_location}}">
<google-map>
...
</google-map>
<template>
You can change a value on the model when core-axax has finished and wrap the other elements with a <template if="{{ajaxHasFinished}}">...</templ<te>
Besides what others have said, an another way is demonstrated in the tutorial https://www.polymer-project.org/docs/start/tutorial/step-3.html, in which you create another element to do the ajax thing, and use it in your original element. The data transfer is achieved through attributes and data binding.
I think it's a better way because you separate the data display with data fetching, making it look better in software engineering.
P.S. I've tried what other answers said, but I found out it didn't matter whether you use if condition or not.

How to handle testing an HTML control that lacks sufficiently unique attributes?

I'm using Coded UI Test to test a web application.
I have a class Locator that I use to stash the specifics needed for CUIT to find a control. To operate on a control, a page object specifies the locator, not the control, and lower-level functions find the control and perform the operation.
Right now, my class has:
Locator name.
One or more attrName/attrValue pairs that can locate the HTML element for the control.
An operator (Contains or EqualTo) that specifies the matching needed.
The problem: Some of the controls I need to operate on don't have enough unique attributes to allow them to be found. (Yes, I know the developers should improve their HTML, but I don't control that.) I have been using a locator to find a nearby element, then "walking" in the DOM to get to the element I want. I hate having this DOM-walking code in my page object, even factored into a function.
A possible solution: I'm considering enhancing class Locator so that it can have either the attrName/attrValue pairs or a reference to a function that has the DOM-walking code. One advantage of this is that the page objects would always use a locator object. Another is that when the HTML is improved, the locator could change from DOM-walking code to attrName/attrValue pairs, which would be transparent to the page object.
Still, I think this may be over-complicated.
Is there a better solution to this problem?
Not sure specifically how your locator works, but could you find the closest parent to that object, let's say an HTML Div with an id of "parent", and then count the tag instances underneath? For example:
HtmlDiv id="parent">
HtmlHyperlink>text1</
HtmlHyperlink>text2</
Would require the following code:
public HtmlHyperlink text2Link
{
get
{
HtmlDiv parentDiv = new HtmlDiv(browser);
parentDiv.SearchProperties["id"] = "parent";
HtmlHyperlink target = new HtmlHyperlink(parentDiv);
target.SearchProperties["TagInstance"] = "2";
}
}
This would find the 2nd hyperlink under the parent object. (Tag instances are not zero based).
Then, you'd just interact with your object as needed:
Mouse.Click(text2Link);
for example.