I have the following use case.
The root file in my web project is index.html. I want to create an object that stores user info such that it can be accessed from any polymer web component in the project, without ever passing it to any web component explicitly. Can this be done? This is similar to the Singleton methodology of many object oriented programming language.
Thank you.
If you want any/all components to be able to access the same data then you have to make it global:
window.myData = {};
But this is such a bad idea on so many levels.
This ties all of your components to this data structure and location. No one else and no other app can use these components unless they are willing to manage the exact same data structure.
Instead you need to pass the required data into each component. Yes, that is more work, but it allows the component to be used any where.
If the component needs to get the EXACT same data every time in every condition, then you have the component gather the data.
If the data needs to be able to come from a different endpoint, based on the application, then you need to provide the component with the ability to have its URL defined. This is much like the <img> tag. it has the src property. Sure the <img> tag only displays images and always displays images but the user of the <img> tag can set the src attribute or property to tell the tag where to get the data for the image.
The iron-meta element is designed for this, but the element basically just saves stuff into memory. Just look at what the element does:
Polymer.IronMeta.getIronMeta = function getIronMeta() {
if (singleton === null) {
singleton = new Polymer.IronMeta();
}
return singleton;
};
So I would just go ahead with the already suggested solution:
window.myData = {};
Related
I was reading the article on best practices here. And i came across the following lines:
A developer might attempt to set a property on your element before its definition has been loaded. This is especially true if the developer is using a framework which handles loading components, inserting them into to the page, and binding their properties to a model.
And the proposed solution to solve this problem was:
_upgradeProperty(prop) {
if (this.hasOwnProperty(prop)) {
let value = this[prop];
delete this[prop];
this[prop] = value;
}
}
I have been trying the understand the scenario in which this would happens, and try to understand how this fragment of code solves this problem. I have trying to find any reference material around but wasnt able to find anything similar like this.
Please could someone explain this scenario and what problem are we trying to solve here.
Web Components doesn't fully initialize your element until you call customElements.define('custom-tag', CustomElement); however, any <custom-tag> exists in the DOM as an HTMLUnknownElement as soon as the page renders. So in the period of time between when the page renders and when you call customElements.define(...), it's possible for someone to call something like:
document.querySelector('custom-tag').someProperty = someValue
which would modify the property of the not-yet initialized CustomElement.
Why would this happen?
I think this would most likely come up as a side-effect of using Web Components with a frontend framework (Angular, Vue, etc). These frameworks often have initialization code that happens after render, and there may be situations where a user may not have sufficient control to prevent the framework from initializing before Web Components.
How does the code fragment solve the problem?
The fragment function, _upgradeProperty() is meant to be called within the connectedCallback(), which is called after the Web Component has been fully defined and attached to an existing element. If you have any custom setter in your class, like:
class CustomElement {
set someProperty(value) {
this._someProperty = value.toLowerCase();
}
}
Then it's possible the property was set before the setter existed, meaning the raw value was saved directly to the instance's someProperty property, instead of being converted to lowercase and saved to _someProperty. Deleting the property and reassigning it after the setter has been defined ensures that the value is properly processed (in this case, made lowercase and saved in the right location).
So I have a Vue component which has two functions. One attaches some data and populates various tags with that data, another gets the data from a json file and parses through it - applying it to the other function.
(pseudo-code ahead!)
mounted: function() {
function listBuilder(data) { some code }
$.get("some-json"), function (data) {
[some code...]
listBuilder(data);
}
}
On the page itself, this component exists twice.
<section>
<my-component type="map"></my-component>
</section>
<aside>
<my-component></my-component>
</aside>
One component renders out the data in map form, while the other renders it out as a list. This all works just fine & dandy, except that on the map the data is rendered 2x - because, as you might have guessed, the component's logic is run twice - getting the json twice and processing it twice.
Is there a native "Vue" way to have (or designate) the code in the component to only run once on a page? I have a rather (in my opinion), hacky way of avoiding this right now, by applying a property to one of the components ("dumb"), that essentially skips some of the logic via a check if that property exists. I feel there has got to be a more elegant and native way to handle this, however, but have come up dry in my google searches.
One possible way is to have the component data loading moved to another parent element. Other way of doing this is to have one global store (like vuex) and then load the data out of it. This is just the type of problem vuex is solving. If you don't want to use vuex just use the browser's Window.sessionStorage it is well supported and you can store all the data you need in it. It is session based so you won't need to load the information every time.
Well I'm sure you'll get different responses, but I would have to agree with #pinoyyid and suggest extracting http part into a service for start, and then I would implement Vuex ( centralized local data that can be fairly easily integrated with Vue ) and then use Vuex actions and getters to get and process data. This will completely separate your vue component from fetching and data processing. You will only fetch your data once and then use it as many times as you'd like. And last but not least testing will be possible unlike now.
I am fairly new to Polymer, and only just studied how data binding works. I am porting an existing Dojo application, where there would be:
1) A single store (holding data) for each URL
2) A message from the server when a store element was updated
As a result, a dynamically made select box which depended on data in the store would automagically have an extra item if anywhere in the application a user added an item to the store (which held the data)
I am trying to replicate something like this in Polymer.
Use case: imagine an URL like this: /app/categories. By querying it with an HTTP GET, you end up with a JSON of all the categories available. While the app is running, the server might notify of a new element in /app/categories. as a result, all of the selects in the application would then have the extra item automagically.
In Polymer, I learned how to bind a property in the current element to a property in a contained element. I understand how this happens with the right events being fired etc. So, the idea would be to create a select where the items are generated by a dom-repeat, which would be bound to... a somehow global variable (?).
But... is it even possible to bind the property of a contained element to a "global" variable, rather than a property of the containing element?
OR, more broadly, is there a pattern (or even an established pattern) to make sure that when a global variable is changed (thanks to a comet message, or whatever), a bunch of elements binding to it will be notified and therefore changed (in this case, the "select" using dom-repeat to show the items!)
Here is a JSBin that shows how to create a menu via iron-ajax At this point what's missing to the JSBin is the simulation of a server push about a data change, as well as a way to have all of the menus update at the same time.
IMHO the most sane and maintainable pattern is a one way data flow approach (something along the lines of Flux or Redux (which is a bit simpler).
There is one global state object that exists as as a graph structure and the data flows down your component tree (starting with the root component).
Each component has well defined input properties and receives data from the parent component (using data-binding) and passes on parts of the data to its children. When a component changes state, it fires an event which bubbles up the component tree up to your root component that can then update your global state object (which again flows down your component tree), communicate with the backend, etc.
I can also recommend this video from the Polymer 2015 summit, which explains a similar approach (mediator pattern).
I am just getting started with Flight.js and realized that component instances share local variables, but didn't find anything about it in the documentation.
This is what i mean:
flight.component(function () {
var sharedBetweenAllInstances = true;
this.notShared = true;
}).attachTo('.multiple-elements');
As example, if a component should count clicks on it, it could increment this.clicksCount for the number of clicks on each single instance, and increment var totalClicks for the total number of clicks on any instance of the component.
I didn't find anything about this in the documentation, so I wonder if flight components should be used this way?
Thank you!
I don't think that's a good idea (probably why they don't mention it in the docs). The function you setup as your "component" is actually applied as a functional mixin, along with any other mixins your component uses. So, while you might be able to access that variable when doing an .attachTo('.multip-selector') where you're setting up an instance on each of many components, you could still run into problem if attaching individually, or if the shared variable controls resources in which a race condition to access that shared resource becomes problematic.
From a "component" standpoint, you're better off pulling out any shared state into a separate data component or controller type component that can receive updates form the individual components and broadcast the shared state when it's updated.
Here's an example I put together using that scenario via jsbin: http://jsbin.com/qecupi/edit?js
I was wondering what the best practice or convention is when creating stores in Flux when working with an API
Let's say we have a list of 'projects', the API call would eventually fill a Store called ProjectStore in _projects
Then, when a user selects a project, you want to load the Project specific data. Would you add this to the same ProjectStore as _activeProject, or create a seperate Store for it?
Same for when you load the Todo's within that Project. It would make sense to put these in a TodoStore, but what about a specific Todo within the Todos within the Project?
I hope the above makes sense :)
I would use the ProjectStoreto store both _projectsand _activeProject.
I have done as a rule in my React projects to create a new store for each model.
For instance: Let's say that I have an application that serves messages and accounts. I would then have a MessageStoreand an AccountStore. Then use these accordingly to their domain.
E.g., when I want to get some messages from the backend (through an API), I store them in the MessageStore. The same goes for the AccountStore.
As your project becomes larger and larger, you would probably have to reconsider refactoring something into a new store. For instance, if you want to add advertisement to your site, you could create an AdsStore.
My rule of thumb is to try to separate stores by their domain, but don't make the structure more complex than it has to be.
Hope that helped.