Access Shadow DOM polymer elements with meteor - javascript

How do I access the paper-button with id='signin' outside of the Polymer constructor. I need to access it from Template.{template-name}.rendered method. Is there a way to use selector for paper-button?
<!-- Code -->
<dom-module id="app-bar">
<template>
<link rel="import" href="bower_components/iron-media-query/iron-media-query.html">
<iron-media-query query="min-width: 1008px" query-matches="{{largeScreen}}">
</iron-media-query>
<template is="dom-if" if="{{largeScreen}}">
<span class="separator">
<link rel="import" href="bower_components/paper-button/paper-button.html">
<paper-button id="signin" on-click="login" raised>Sign in</paper-button>
</span>
</template>
<template is="dom-if" if="{{!largeScreen}}">
<span class="title"></span>
</template>
</template>
<script>
Polymer({
is: "app-bar",
login: function() {
FlowRouter.go('/login');
}
});
</script>
</dom-module>
<!-- In the landing-page.html -->
<landing-page>
<link rel="import" href="app-bar.html">
<app-bar></app-bar>
</landing-page>

The easy, less prone way to breakage... (with shadowRoot you will potentially break in Polyfil'd browsers) get a reference to your 'app-bar' element and from there use the $ property id shortcut. If you cannot find the element via [landing-page].querySelector('app-bar') then try Polymer.dom(landing-page-element.root).querySelector('app-bar'). ($ shortcut only works for elements given an ID in that particular elements template, so for your app-bar this will work with signin. It would not work if the elements/ids were generated by a dom-repeat though.
document.querySelector('landing-page').querySelector('app-bar').$.signin;

Related

How do you activate alpinejs?

I'm trying to add AlpineJS to a very simple html page that I'm working on and the package is being executed (from cdn) but it doesn't seem to get activated correctly. Even on this small snippet of HTML, it doesn't work:
<html>
<head>
<script src="https://cdn.jsdelivr.net/gh/alpinejs/alpine#v2.x.x/dist/alpine.min.js" defer></script>
</head>
<body>
<h1 x-show="false">hide me</h1> <!-- doesn't work-->
</body>
<script type="text/javascript">
console.log($el); //undefined
</script>
</html>
This is also loaded into a codepen where the problem can be observed: https://codepen.io/dwarburt/pen/gOgZyeR
I'm sure I've just missed a step, but what could it be? AlpineJS is executing its initialization routines, you can tell from the debugger.
To initialise an AlpineJs component you'll need an x-data attribute on the parent container:
<div x-data="{
isShowing: false
}">
<h1 x-show="isShowing">I am hidden</h1>
</div>
This contains an object with properties and functions you can use within the component instance.
It's definitely worth reading through the docs in the repo here: https://github.com/alpinejs/alpine#use
I have adjusted your example in order to achieve the result you require, along with an additional example so you can see how multiple object properties can exist and used within your Alpine.js components.
x-data does not need to be initiated on the body tag, however nested components will retrieve the object property from the closest x-data property match.
You can access from child nodes of nested x-data objects the properties.
Careful of your property naming conventions if you don't wish to overwrite proceeding object properties.
I would also suggest reading Build a Drop Down along with Toggle Element
Reading these points will be helpful in understanding the below example in further detail.
<html>
<head>
<script src="https://cdn.jsdelivr.net/gh/alpinejs/alpine#v2.x.x/dist/alpine.min.js" defer></script>
</head>
<body x-data="{show: false, button: 'Toggle'}">
<button #click="show = ! show" x-text="button"></button>
<span x-show="show">
<h1 #click.outside="show = false">hide me</h1> <!-- doesn't work-->
</span>
</body>
</html>

How to use intro.js with Polymer 2?

I want to use intro.js for first-time user experience in my Polymer 2 application. Below is the code how I'm trying to use but it's not working out for me.
<base href="https://polygit.org/polymer+v2.0.0/shadycss+webcomponents+1.0.0/components/">
<script src="webcomponentsjs/webcomponents-lite.js"></script>
<link rel="import" href="polymer/polymer.html">
<script src="intro.js/minified/intro.min.js"></script>
<link rel="import" type="css" href="intro.js/minified/introjs.min.css">
<dom-module id="my-app">
<template>
<style>
</style>
<p class="line1" data-intro='Hello step one!' data-step="1">Line 1</p>
<p class="line2" data-intro='Hello step two!' data-step="2">Line 2</p>
<p class="line3" data-intro='Hello step three!' data-step="3">Line 3</p>
<p class="line4" data-intro='Hello step four!' data-step="4">Line 4</p>
</template>
</dom-module>
connectedCallback(){
super.connectedCallback();
introJs().start();
}
Here's the Codepen for the same. Since, intro.js is not a polymer web component so, I'm not able to figure out how to use it with Polymer 2.
It won't work as you have it right now
Asides
If you are importing external styles into a polymer element, you need to use style-modules Read here , henceforth, preferably.
The link rel=import type=css is deprecated, but If you still want to use them, they should be placed inside your dom-module for polymer to shim it.
intro.js , can not be scoped to your polymer element. JS is scoped via IIFE's and you might have to code a wrapper to do that yourself for any external scripts
That is if you strictly want everything scoped.
Regarding Your question
The problem is, that intro.js, can not access DOM inside your element.
Hence, it can not reach any of your P tags
One solution, is to move / distribute them to an outer scope like the document itself, by using slots
<dom-module id="my-app">
<template>
<!-- uncomment this, if you have a style module pointing to intro'scss only-->
<!--<style include="intro-css"></style>-->
<slot>
</slot>
</template>
</dom-module>
Now, all you need to do is, place all your DOM inside the tags <my-app></my-app>
Only then will intro.js work on them. plunker

How to access root element's text in Polymer?

I'm writing an Polymer element that's supposed to be used like this:
<x-elem>Some text</x-elem>
The element would transform the text content. But when I try to access it in attached callback, it's empty:
attached: function() {
var text = this.root.textContent;
console.log(text); // Outputs ''
}
Frankly, the number of all child nodes is 0:
attached: function() {
console.log(this.root.childNodes.length); // Outputs 0
}
According to these docs I would think that at least my attempt at getting child nodes is correct, but apparently I do something wrong here. Perhaps I need to put something in my template (right now it's simple <template></template>, but it is not clear what.
this.root provides access to the element's local DOM (i.e., the DOM locally declared in the <dom-module>'s template), but you're trying to access light DOM (i.e., the DOM passed in). Use Polymer.dom(this).textContent for that:
HTMLImports.whenReady(() => {
Polymer({
is: 'x-foo',
attached: function() {
console.log('textContent:', Polymer.dom(this).textContent);
}
});
});
<head>
<base href="https://polygit.org/polymer+1.7.0/components/">
<script src="webcomponentsjs/webcomponents-lite.min.js"></script>
<link rel="import" href="polymer/polymer.html">
</head>
<body>
<x-foo>hello world</x-foo>
<dom-module id="x-foo">
<template>
</template>
</dom-module>
</body>

Access file selected with paper-input

I'm trying to upload a file chosen through a Polymer <paper-input type="file" id="filepicker"> element but when i try to access the file with:
var file = this.$.filepicker.files
i get a files is not defined error.
I haven't found any other methods to access files in paper inputs so I'm not sure what the problem is here.
Any help would be appreciated!
The files property is found on the inner <input> element of <paper-input>, which you could access with <paper-input>.inputElement.inputElement. So you would use this:
this.$.filepicker.inputElement.inputElement.files[0];
Note: In earlier versions of <paper-input>, the inner <input> was accessed with this.$.filepicker.inputElement, but it has since been refactored to have another container (hence, this.$.filepicker.inputElement.inputElement).
HTMLImports.whenReady(() => {
Polymer({
is: 'x-foo',
_handleFiles: function() {
console.log(this.$.input.inputElement.inputElement.files[0]);
}
});
});
<head>
<base href="https://polygit.org/polymer+1.10.1/components/">
<script src="webcomponentsjs/webcomponents-lite.js"></script>
<link rel="import" href="polymer/polymer.html">
<link rel="import" href="paper-input/paper-input.html">
</head>
<body>
<x-foo></x-foo>
<dom-module id="x-foo">
<template>
<paper-input type="file" id="input"></paper-input>
<button on-tap="_handleFiles">Log file info</button>
</template>
</dom-module>
</body>
codepen

Pass DOM nodes to Polymer as attributes

Ok, so I'm defining a polymer object like this:
<link rel="import" href="../bower_components/polymer/polymer.html">
<polymer-element name="my-element" attributes="content">
<template>
<div class="someclass">
{{content}}
</div>
</template>
<script>
Polymer({});
</script>
</polymer-element>
Which works fine if I instantiate it as:
<my-element content="test"></my-element>
However, I'd like to be able to pass HTML inside the element. If I do this:
<my-element content="<div>test</div>"></my-element>
The HTML is not added to the DOM, but displayed as text. Is it possible to pass HTML inside a polymer element? Or am I doing something completely wrong here?
Thanks for any help!
Here's some hackish code I made that may answer your question.
http://jsbin.com/hedutu/edit?html,output
Basically, I created an observer for an attribute that accepts DOMs in string format and then inserted that dom into a local dom node.

Categories

Resources