Dynamic paper-toolbar background in Polymer - polymer

I'm using Polymer 1.0 Starter Kit. I'm trying to change toolbar's background and color when changing routes.
<paper-scroll-header-panel main id="headerPanelMain" condenses keep-condensed-header
header-height="256" condensed-header-height="100">
<paper-toolbar>
<paper-icon-button id="paperToggle" icon="menu" paper-drawer-toggle></paper-icon-button>
<span class="space"></span>
<!-- Toolbar icons -->
<nt-toolbar-icons></nt-toolbar-icons>
<!-- Application name -->
<div class="middle middle-container">
<div class="app-name">[[route.title]]</div>
</div>
<!-- Application sub title -->
<div class="bottom bottom-container">
<div class="bottom-title">[[route.subline]]</div>
</div>
</paper-toolbar>
<div style="height: 1400px;">
<iron-pages attr-for-selected="data-route" selected="{{route.name}}">
<section data-route="home">
{{route.title}} /
</section>
<section data-route="users">
users {{route.params.type}}
</section>
</iron-pages>
</div>
</paper-scroll-header-panel>
</paper-drawer-panel>
Route is defined in elements/routing.html
page('/', function() {
app.route = {
name: 'home',
title: 'noTos+',
subline: ''
}
});
In my shared-styles.html my toolbar is defined this way:
paper-scroll-header-panel#headerPanelMain {
position: absolute;
top: 0;
right: 0;
bottom: 0;
left: 0;
background-color: var(--paper-grey-200, #eee);
/* background for toolbar when it is at its full size */
--paper-scroll-header-panel-full-header: {
background-image: url(../images/headers/bg4.jpg);
}
/* background for toolbar when it is condensed */
--paper-scroll-header-panel-condensed-header: {
background-color: var(--paper-light-blue-600);
}
}
But now I want this color/background-scheme to be changed when the route is changed.
I've tried adding data-route$="[[route.name]]" to paper-scroll-header-panel.
Then I've changed shared-styles.html with the [data-route="home"] selector:
paper-scroll-header-panel#headerPanelMain[data-route="home"] {
--paper-scroll-header-panel-full-header: {
background-image: url(../images/headers/bg3.jpg); //BG CHANGES HERE
}
}
But this doesn't work.
Any other ideas?

Custom styles are only applied at creation time. If you have dynamic changes like you do here, you need to call updateStyles on you custom element or Polymer.updateStyles for a global update. In your case, you would do that when the route changes. You can find more info in the documentation.

you can do the following.
<paper-toolbar id="mainToolbar" class="tall" style$={{computedStyleHandler(color)}}>
computedStyleHandler: function(color){
return 'background-color:' + color + ';'
}

Related

CSS - material web components implementing drawer with the hero section

I have started working with material web components on a new project for the first time. I am trying to use their persistent drawer with the hero section on a page, where I also have a toolbar.
The template looks like this:
<div id="app">
<aside class="mdc-drawer mdc-drawer--persistent mdc-typography">
<nav class="mdc-drawer__drawer">
<header class="mdc-drawer__header">
<div class="mdc-drawer__header-content">
Header here
</div>
</header>
<nav id="icon-with-text-demo" class="mdc-drawer__content mdc-list">
<a class="mdc-list-item mdc-list-item--activated" href="#">
<i class="material-icons mdc-list-item__graphic" aria-hidden="true">inbox</i>Inbox
</a>
<a class="mdc-list-item" href="#">
<i class="material-icons mdc-list-item__graphic" aria-hidden="true">star</i>Star
</a>
</nav>
</nav>
</aside>
<header class="mdc-toolbar mdc-toolbar--fixed demo-toolbar">
<div class="mdc-toolbar__row">
<section class="menu mdc-toolbar__section mdc-toolbar__section--align-start">
menu
<span class="mdc-toolbar__title">Title</span>
</section>
<section class="mdc-toolbar__section">
Section aligns to center.
</section>
<section class="mdc-toolbar__section mdc-toolbar__section--align-end" role="toolbar">
file_download
print
bookmark
</section>
</div>
</header>
<div class="page-content">
<div class="landing-page-hero">
</div>
</div>
</div>
I don't have much css, I have copied from their demo the css for the page-content and added css for the landing-page-hero:
body {
margin:0;
}
.page-content {
display: inline-flex;
flex-direction: column;
flex-grow: 1;
height: 100%;
box-sizing: border-box;
}
.landing-page-hero {
min-height: 400px;
height: 45vh;
width: 100vw;
background-image: url('/img/hero-image.jpg');
background-size: cover;
background-repeat: no-repeat;
background-position: 90% 60%;
display: flex;
align-items: center;
color: $white;
}
For some reason the drawer won't open when I have a div element with the id="app" that wraps the whole page. I am using this div element to mount Vue.
So, if I remove this element, then the drawer opens but only above the image:
But, like I said, I need this element to mount Vue, and when I have it then the drawer is not visible on clicking the menu, and the hero is not immediately below the toolbar, there looks like their is margin-bottom from the drawer that pushes it further down.
How can I make this work? So, that I have a toolbar with the drawer and a hero section immediately below the toolbar?
I have fixed the js issue part with requiring the material package after mounting the Vue on #app element:
window.Vue = require('vue');
const app = new Vue({
el: '#app'
});
window.mdc = require('material-components-web/dist/material-components-web')
window.mdc.autoInit();
require('./material/drawer');
And, then in the css, I have set the display of #app to display: flex, and then it worked.

Position app-drawer underneath app-header

Using the template from starter kit 2, is it possible to have the app drawer below the app-header? Right now the app drawer starts from the top of viewport and is columnized next to app-header.
I would like my app to be like google keep and google cloud console where the app header spans the entire width of the viewport and the app drawer begins underneath.
After reading the element catalog for app-layout, I did not see a offical api/attribute to set this. I've tried a few things but no success:
<app-drawer-layout fullbleed>
<!-- Drawer content -->
<app-header condenses reveals effects="waterfall">
<app-toolbar>
<paper-icon-button icon="menu" drawer-toggle></paper-icon-button>
<div main-title>My App</div>
</app-toolbar>
</app-header>
<app-drawer>
<app-toolbar>Menu</app-toolbar>
<iron-selector selected="[[page]]" attr-for-selected="name" class="drawer-list" role="navigation">
<a name="view1" href="/view1">View One</a>
<a name="view2" href="/view2">View Two</a>
<a name="view3" href="/view3">View Three</a>
</iron-selector>
</app-drawer>
Basically you need to use an app-drawer-layout inside an app-header-layout.
Here is a JSBin with the desired layout.
And the code itself:
<dom-module id="test-app">
<template>
<style>
:host {
display: block;
--app-primary-color: #3F51B5;
}
app-header {
background-color: var(--app-primary-color);
color: white;
}
app-drawer {
top: 64px;
--app-drawer-content-container: {
padding: 0px;
background-color: #eee;
};
}
</style>
<app-header-layout fullbleed>
<app-header fixed shadow>
<app-toolbar id="toolbar">
<paper-icon-button icon="menu" on-tap="_onTap"></paper-icon-button>
<div main-title>Stormwind</div>
</app-toolbar>
</app-header>
<app-drawer-layout>
<app-drawer id="drawer">
drawer content
</app-drawer>
<div>
main content
</div>
</app-drawer-layout>
</app-header-layout>
</template>
<script>
Polymer({
is: 'test-app',
properties: {
},
ready: function() {
},
attached: function() {
},
_onTap: function() {
this.$.drawer.toggle();
}
});
</script>
</dom-module>
NOTE
You need to manually handle the drawer button (the drawer-toggle property won't work).

Similar attribute like drawer-toggle but does not toggle the drawer

Is there anything like drawer-toggle except that it doesn't toggle the menu? I want to add a similar attribute to paper-icon-button to show/hide the icon button based on whether the drawer is shown or not. I know I can get the boolean from app-drawer-layout.narrow, but my code is not exactly like the following and it's not easy to have an reference to <app-drawer-layout>. The following is just an example of providing the context of what I meant by drawer-toggle.
<app-drawer-layout>
<app-drawer>
drawer-content
</app-drawer>
<app-header-layout>
<app-header>
<app-toolbar>
<paper-icon-button icon="close" drawer-toggle></paper-icon-button>
<div main-title>App name</div>
</app-toolbar>
</app-header>
main content
</app-header-layout>
</app-drawer-layout>
You can bind a boolean property to the app-drawer-layout's narrow property and use this with an observer to show/hide the paper-icon-button. Example:
<dom-module id="test-app">
<template>
<style>
.hide {
display: none;
}
</style>
<app-drawer-layout fullbleed narrow="{{visible}}">
<app-drawer id="drawer">
drawer content
</app-drawer>
<app-header-layout>
<app-header>
<app-toolbar>
<paper-icon-button id="button" icon="menu" on-tap="_onTap"></paper-icon-button>
<div class="title" main-title>App name</div>
</app-toolbar>
</app-header>
<div>
main content
</div>
</app-header-layout>
</app-drawer-layout>
</template>
<script>
Polymer({
is: 'test-app',
properties: {
visible: {
type: Boolean,
observer: '_visibleChanged'
}
},
_onTap: function() {
console.log(this.visible);
this.$.drawer.toggle();
},
_visibleChanged: function(value) {
this.toggleClass('hide', !value, this.$.button);
}
});
</script>
</dom-module>
Note that now you need to manually handle the drawer toggle (_onTap function).

Polymer 1.0 a/custom element under toolbar clicking bug

I am encountering some problems with a custom element created by me, called <little-game></little-game>.
This is <little-game></little-game> template code :
<template>
<a href="{{link}}">
<paper-material elevation="1">
<paper-ripple></paper-ripple>
<iron-image src="{{img_url}}"></iron-image>
<div id="description">{{name}}</div>
<div id="category">{{category}}</div>
</paper-material>
</a></template>
And the :host css of this element:
:host {
display: inline-block;
text-decoration: none;
z-index:1;
}
Those <little-game></little-game> elements are displayed in a page and inside this page i have a <paper-scroll-header-panel> and a <paper-toolbar>. The problem is when i scroll down and the .tall <paper-toolbar> gets smaller, i can click through the <paper-toolbar> on <little-game>/<paper-ripple> element.
<paper-ripple> css :
paper-ripple {
z-index:1;}
mainToolbar html :
<paper-toolbar id="mainToolbar" class="tall">
<paper-icon-button id="paperToggle" icon="menu" paper-drawer-toggle></paper-icon-button>
<span class="flex"></span>
<!-- Toolbar icons -->
<!--paper-icon-button icon="refresh"></paper-icon-button-->
<paper-icon-button icon="more-vert"></paper-icon-button>
<!-- Application name -->
<div class="middle middle-container center horizontal layout">
<div class="app-name">App title</div>
</div>
<!-- Application sub title -->
<div class="bottom bottom-container center horizontal layout">
<div class="bottom-title paper-font-subhead">App subtitle</div>
</div>
</paper-toolbar>
mainToolbar css :
#mainToolbar {
z-index:3;}
So the main problem is about that i can click the <little-game></little-game> element through the toolbar.
There is an image to understand what i am talking about in a better way:
I think you need to cancel the tap event from propagating through, try adding an on-tap event handler on the paper-toolbar e.g.
<paper-toolbar id="mainToolbar" class="tall" on-tap="{{cancelEvent}}">
then add the function to cancel it
cancelEvent: function(event) {
event.stopPropagation();
}

Polymer core-scaffold element not showing inside core-pages

I have been playing with polymer's core-scaffold element and I quite like it. However, for the particular app I'm developing, the core-scaffold cannot be the top level layout element for the entire app. I require a main application toolbar to always be displayed and an initial page that is not controlled by a scaffold layout. In other words, the scaffold-element is the main layout element, but only for one of the sub-pages/sub-elements of the application. In order to accomplish this, I'm trying to make the scaffold-controlled polymer element selectable via core-pages or core-animated-pages (starting with core-pages for simplicity sake, and then migrating to core-animated-pages once I understand how that works). The scaffold element loads without any difficulty when not inside core-pages. However, when used inside core-pages and it is selected, the main application toolbar is displayed but the scaffold element does not (no errors in Chrome console). In other words, an empty display under the main app toolbar. Can anyone shed some light on this? Is it some sort of styling problem perhaps?
Here is the high level app element code stripped down to the essentials to demonstrate the problem (imports not included):
<polymer-element name="my-app">
<template>
<style>
core-header-panel {
/* height: 100% fails here on some browsers */
height: 100vh; /* 100% of the viewport height */
}
core-toolbar {
background-color: #5264ae; /* Google Blue ; */
color: #fff; /* White */
font-weight: 700; /* Boldish font */
}
</style>
<!-- HIGH LEVEL APP LAYOUT ELEMENT -->
<core-header-panel id="appHeader" mode="standard">
<!-- OUTER APP TOOLBAR ELEMENT -->
<core-toolbar id="appToolbar">
<paper-icon-button id="navicon" icon="arrow-back"></paper-icon-button>
<span flex>App Name</span>
<paper-icon-button id="searchbutton" icon="search"></paper-icon-button>
</core-toolbar>
<!-- MAIN CONTENT ELEMENTS -->
<core-pages id="mainPages" selected="{{selectedPage}}">
<my-default-page-element name="firstPage" on-core-activate="{{pageSelect}}"></my-default-page-element>
<my-scaffold-element name="scaffoldPage"></my-scaffold-element>
</core-pages>
</core-header-panel>
</template>
<script>
Polymer('my-app', {
selectedPage: 'firstPage',
//selectedPage: 'scaffoldPage',
pageSelect: function () {
this.showPage();
},
showPage: function () {
//this.selectedPage = "scaffoldPage";
this.$.mainPages.selected = "scaffoldPage";
}
});
</script>
and here is the scaffold-element code stripped down to its essentials as well (also sans imports), just for sake of completeness:
<polymer-element name="my-scaffold-element">
<template>
<style shim-shadowdom>
core-toolbar {
background-color: #5264ae; /* Google Blue ; */
color: #fff; /* White */
}
core-scaffold::shadow core-toolbar {
background-color: #5264ae; /* Google Blue ; */
color: #fff; /* White */
}
core-scaffold::shadow core-header-panel {
background: #FFF; /* White */
color: black;
}
/* For use with the shim-shadowdom directive interpreted only when on a non-webcomponent/shadowdom native platform */
/* (i.e. I noticed the above styling wasn't being applied by FireFox */
core-scaffold #main core-header-panel {
background: #FFF; /* White */
color: black;
}
</style>
<core-scaffold id="contentscaffold">
<core-header-panel id="innerHeader" navigation flex>
<core-toolbar id="innerToolbar">
<span>Options</span>
</core-toolbar>
<core-menu>
<core-item label="Subpage1" on-tap=" {{ pageTapAction }}"></core-item>
<core-item label="Subpage2" on-tap="{{ pageTapAction }}"></core-item>
<core-item label="Subpage3" on-tap="{{ pageTapAction }}"></core-item>
<core-item label="Subpage4" on-tap="{{ pageTapAction }}"></core-item>
<core-item label="Subpage5" on-tap="{{ pageTapAction }}"></core-item>
</core-menu>
</core-header-panel>
<span id="sectionTitle" tool>Subpage1</span>
<core-pages id="pages" selected="0">
<section id="sectionPage1">
<my-subpage-one-element></my-subpage-one-element>
</section>
<section id="sectionPage2">
<div>Page 2 polymer element here</div>
</section>
<section id="sectionPage3">
<div>Page 3 polymer element here</div>
</section>
<section id="sectionPage4">
<div>Page 4 polymer element here</div>
</section>
<section id="sectionPage5">
<div>Page 5 polymer element here</div>
</section>
</core-pages>
</core-scaffold>
</template>
<script>
Polymer('my-scaffold-element', {
pageTapAction: function(e, detail, sender) {
for(var key in sender.parentNode.children) {
if (sender.parentNode.children[key].label == e.target.label) {
this.$.pages.selected = key;
this.$.sectionTitle.innerText = e.target.label;
}
}
}
});
</script>
Anybody else run into problems with using a scaffold element inside core-pages? Once again, just to re-iterate, the scaffold element loads perfectly fine on its own when loaded outside of core-pages.
UPDATED:
For the sake of completeness and to show all CSS styling involved in this scenario, here is the index page that imports the high level app element itself. Note the use of fullbleed:
<html>
<head>
<title>Application Title</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0">
<meta name="mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-capable" content="yes">
<script src="/components/platform/platform.js"></script>
<link rel="import" href="/components/my-app-components/my-app.html">
<style>
html, body {
height: 100%;
margin: 0;
}
body {
font-family: sans-serif;
}
</style>
</head>
<body fullbleed unresolved>
<template is="auto-binding">
<my-app></my-app>
</template>
</body>
</html>
I think the issue is that core-pages doesn't have a height in your version.
I threw together an example for you. I'm using the fullbleed attribute to set the body to 100vh. Then using the fit attribute to make my element cover the entire page. Then setting core-pages to have a height of 100%.
<body fullbleed>
<polymer-element name="x-foo" fit>
<template>
<style>
core-pages {
height: 100%;
}
</style>
<button on-tap="{{prevPage}}">Prev page</button>
<button on-tap="{{nextPage}}">Next page</button>
<core-pages id="pages" selected="0">
<div>Page 1. Not so exciting</div>
<core-scaffold>
<core-header-panel navigation flex mode="seamed">
<core-toolbar>Application</core-toolbar>
<core-menu theme="core-light-theme">
<core-item icon="settings" label="item1"></core-item>
<core-item icon="settings" label="item2"></core-item>
</core-menu>
</core-header-panel>
<div tool>Title</div>
<div>Content goes here...</div>
</core-scaffold>
</core-pages>
</template>
<script>
Polymer({
prevPage: function() {
this.$.pages.selected = 0;
},
nextPage: function() {
this.$.pages.selected = 1;
}
});
</script>
</polymer-element>
<x-foo></x-foo>
</body>
Here's a jsbin. Click the next button to see the core-scaffold page.