How do I access variables in custom elements in Aurelia? - javascript

I have a custom element on my page and need to access a variable on the app.js from the custom element. Is the only way to bind the data I need to the custom element?
<custom-element data.bind="data"></custom-element>
The reason I ask is that I am running a loop to create multiple custom-elements and don't want to bind 5 variables to each custom element like that. Just asking if there is another way?

A custom element's template cannot access the outer scope. This is by-design. It ensures custom elements are portable. This mirrors the way standard elements work such as <div>, <a>, etc. You can use those elements anywhere. The only way to pass them data is via their attributes.
If you want to tightly couple your custom element to the outer view model, you could do something like this:
<custom-element app.bind="$this"></custom-element>
but this is not recommended

Related

Is there a way to get a list of all global HTML attributes programmatically?

The list of global HTML attributes is quite large if you include every possible event listener, plus it's subject to change as browsers evolve.
Is it possible to use JavaScript to generate a comprehensive list of these attributes programmatically without explicitly defining them? (e.g. from a built-in class or element instance)
You can get most of them by looking at HTMLElement.prototype, or Element.prototype:
console.log(Object.keys(HTMLElement.prototype));
console.log(Object.keys(Element.prototype));

Angular directive as shorthand for multiple directives

I'm trying to make an angular directive that combines ng-mouseover, ng-mouseout, and ng-mousemove. Ideally, I'd like to have a custom attribute hover="thing" which, through a custom directive, would be shorthand putting all three of these mouse event attributes in an element, each calling some function with thing as a parameter.
Is there an easy way to do this? I can use a template, but I want this directive to simply be able to be added to any existing element, from images to divs. I don't want to have to make separate directives for every type of element I might want to use it on.
What is the best way to accomplish this?

Where to implement ng-click functions, controller or directive?

I'm a beginner in AngularJS, I understand most of the mechanics but I'm still grasping the "culture".
I'd like have clean separation between my HTML, DOM, data and communications.
My impression of a controller is a module that implements a "data" model, but is void of UI semantics (i.e. DOM manipulation).
However in my HTML, if I use an ng-click it is the controller's scope that is accessed for the click function implementation, which more then likely will need to call back into the DOM.
So where should I implement my click functions if I do not want DOM manipulation in my controller? Are DIRECTIVES the universal answer to this?
Suppose I have 2 controls on a page that need to interact with each other, should I create a directive on the parent of those controls parent that implements the click functions of both child controls? Or perhaps create a directive for each control and possibly pass the ID of the other control as an attribute? OR maybe a directive for the parent AND children?
--------- UPDATE 1 -----------
The following HTML is a simplified and contrived example that [hopefully] illustrates my question.
<div id="searchComponent">
<input id="txtSearchText" ng-keyup="..."/>
<input name="Go" id="btnDoSearch" ng-click="..."></input>
<div id="autoCompleteResults"></div>
<div id="fullResults"></div>
</div>
As the user types in the txtSearchText, the autoCompleteResults is populated, factoring in the usual minimum characters and timouts.
When the user presses or clicks the btnDoSearch, the autoCompleteResults is cleared/hidden and the fullResults is populated.
Finally, if the user begins typing new txtSearchText, the fullResults would be cleared/hidden and the autoCompleteResults is again seen with results.
Any guidance would be appreciated!
So where should I implement my click functions if I do not want DOM manipulation in my controller? Are DIRECTIVES the universal answer to this?
DOM manipulations, in my opinion, means something like document.querySelector(), addCliss, etc. ng-click is the event, which is supposed to deal with some business logic. Put it in the controller is fine.
Of course, directive is your another choice. directive is usually used to extract some reuseable components, such as modal, across different pages. If you repeat some code in different controllers, consider extracting them to directives or service.
Suppose I have 2 controls on a page that need to interact with each other,...
In short: use service, which is designed for that scenarios.
The general philosophy is to reference the DOM explicitly as little as possible. Most (if not all) things you want to do can be done by binding an aspect of you HTML element to a property on $scope, and manipulating that property. So you never have to do some like "Change the class of <span id="foo"> to red now that isRed is true". Instead you would have <span ng-class="{ red: isRed }>". So if you have two click handlers that share information, it's perfectly valid to have them change some common variable in your controller, and have state of the UI accordingly with DOM bindings. Directives are used more for reusing DOM elements, or when you do have to explicitly refer to DOM elements, i.e. adjusting the scroll properties of a div. You could use a directive to add the same click handler to many elements for example. Services can be used to share information, although if both of the controls belong to the same scope there's less of a reason to do that.

Using and Communicating with Directive from different Controllers

I would like to create a directive that is similar to a control. It should be able to be instantiated from "anywhere" and I want to call functions on it's scope from a parent scope/controller.
A very easy example would be:
I have a special directive called myContactForm (which can be used in different places and pages). Now this myContactForm, in it's templace, uses the directive myEditControl. myEditControl is, when you look at the template nothing but an input and a button and in the scope has the function "clear()" so you can delete whatever is inside the input and maybe other functions.
Now when something happens in myContactForm (for example a button is pressed or a broadcast is received or whatever) I want to call "clear()" on the myEditControl that's inside it. Just like it was a normal control.
How would that be done?
I know about the require but that only works for parents and I would have to know the Controllername of the Directive that uses myEditControl. Instead I want any View/Controller to be able to use myEditControl. And I cannot require the myEditControl-Controller from myContactForm because it is a child not a parent.
What is the technique used in angular to solve these kind of problems?
My idea was to transmit a callback or "myContactForm"-Scope to the myEditControl with an attribute so the myEditControl can "register" itself on the parent and the parent then saves that controls scope for later reference and calling of functions. This seems very hacky though....

Publishing property changes from polymer element selectively

I am tying polymer elements in with an existing framework and I am looking for a way to publish events to my framework when certain properties are set on my elements, but only when they are set from a source other then my framework.
For example, I have a custom input element with a "caption" attribute. If data binding inside my elements or some source other than my framework sets the caption property on my control, I want an event published to my framework informing it that the caption property changed, but if my framework sets the caption property, I do not want to publish the event.
I currently publishing these events in an observe block. I have a function on my elements called setFromExternalModel(prop, value) that I use to set the value of a property from my framework. If there were some way for me to pass data from this function on to the observe block, I could prevent the event from being published, but I haven't been able to come up with an elegant way to do this.
Thoughts?
Why is it important to not fire events if your framework changes a property?
It is much less complicated to treat all property changes the same way.
Polymer's core and paper elements have no concept of framework/user data changes, and we haven't thought of any use cases where this would be important.

Categories