Skip to content

Instantly share code, notes, and snippets.

@ishmaelahmed
Last active November 15, 2016 15:16
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ishmaelahmed/e2e99bb22f0ed9edd70ea3a4303a60d4 to your computer and use it in GitHub Desktop.
Save ishmaelahmed/e2e99bb22f0ed9edd70ea3a4303a60d4 to your computer and use it in GitHub Desktop.
How I solved programmatically updating window.location from a child element in a subroute using events && \<app-route>

<app-route>

I was having trouble figureing out how to programmatically change window.location 
from a nested child element. In my case I wanted to send up a uri from dropdown.  
The `select-item` property was bound to  `location`, and `location` had an 
observer `_updateLocation`. 
		<x-dropdown selected-item="{{location}}"></x-dropdown>
		location:{
			type:Object,
			observer: '_updateLocation'	
		} 
I could have set `notify:true` on `location`, but then I would have to pass it 
up the chain. Instead I decided to use an event. 
		_updateLocation: function(item){
			this.fire('update-location-request', {
				uri: location.link
			})
		}
On the element that contians the `app-location` I set up a property called `location`
,it also has an `observer:'_updateLocation'` (these don't have to be named the same 
as on the child, it just worked out that way), . Finally I set up a listener for
`update-location-request`.
		<app-location route="{{route}}" use-hash-as-path></app-location>
		
		//property
		location:{
			type: String,
			observer:'_updateLocation'
		}

		//Methods
		_setRoute: function(){
			this.set('route.path', this.location)
		},	
		_updateLocation: function(e) {
          // will not call `_setRoute` more than once per 100ms
          this.debounce('update-location', function() {
            this._setRoute()
          }, 100);
        },
		ready: function(){
			this.addEventListener('update-location-request', function(e){
				this.location = e.detail.uri
			})
		}

this.debounce

The `debounce` allows things to catch up. It is `debounce` that makes this all work. 
With out it when you use the back button things get wonky, when a subroute triggers 
load of the drop down on the way back in browser history `location` get changed 
mulitple times and `debounce` restores some sanity 
@jroosing
Copy link

jroosing commented Nov 9, 2016

Hi Ishmael, is there a specific reason there are no double quotes at this line:
selected-item={{location}} ?

Also, you can set the listener on your x-component.

<x-dropdown on-location-changed="_handleLocationChanged"></x-dropdown>

@ishmaelahmed
Copy link
Author

@joeyroosing: I forgot the quotes, thanks for pointing that out, it's been updated.

Setting up a listener on the <x-dropdown> assumes <x-dropdown> has it's own property called location and that when an item is selected it updates this prop in <x-dropdown>.

I was thinking of <x-dropdown> as something more generic/agnostic. I was thinking that all <x-dropdown> did was allow the user to select an item, and then make it available to it's parent and siblings.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment