Aurelia - render custom element by name - javascript

Suppose we have a custom element that renders a list of something. It is a selector element, so it does not atter how this something is rendered.
The problem is that this something is quite generic and there are custom elements to actually render it. For example, for countries we add a flag image, for general elements - a fontawesome icon, reputation for users, etc.
What I would like to have
And now I would like to pass the name of the custom element I want to render something with. So instead of this
<selector data.one-way="options" selected.two-way="selected"></selector>
Have something like
<selector element="country" data.one-way="options" selected.two-way="selected"></selector>
And in the selector I would like to have
<${element} content.one-way="el" repeat.for="el of data"></${element}>
What I get
Unfortunately, the code above renders as htmlescaped
<country content.one-way="el" repeat.for="el of data"></country>
So,
Is there a more or less clean way to achieve that? Basically I would like to pass the specify custom elements I want to render in my selector custom element. This post and the answer there have nothing to do with my question.
Using compose as described here... well, it is an option, but I would like to have different custom elements and a slightly different logic in CustomElement js files.
Thanks!
UPD
Well, there's an obvious way to do that by just adding something like a switch statement in the view
<country ... if.bind="el.type === 'country'"></country>
<phone ... if.bind="el.type === 'phone'"></phone>
<user ... if.bind="el.type === 'user'"></user>
But that would make the selector element dependent on country, user etc. So I would not like that.

I believe easiest way is using the compose tag (like you've mentioned):
<compose model.bind="item" view-model="widgets/${item.type}"></compose>

I found couple possible solutions, they may seems more complicated then compose.
#bindable({
name:'myProperty', //name of the property on the class
attribute:'my-property', //name of the attribute in HTML
changeHandler:'myPropertyChanged', //name of the method to invoke when the property changes
defaultBindingMode: ONE_WAY, //default binding mode used with the .bind command
defaultValue: undefined //default value of the property, if not bound or set in HTML
})
You can find more details there http://www.sitepoint.com/extending-html-aurelia-io-way/

Related

Is it bad form to use html class attribute as a variable

I am wondering if the html class attribute should only be used for styling. Is there any drawback to using the class attribute as a variable. The W3 spec http://www.w3.org/TR/html5/dom.html#classes does not specify one way or another but, all examples and training point in the direction of styling only for multiple objects.
In my case I want to use the class attribute as variable that matches the key value in a object array. For example in my Javascript code I have an object that has a number of key/value pairs. On my web app I have a number of save buttons. When a save button is clicked I grab the parents class attribute value and use it as the key for the object to know which value to change. The class attribute on the parent has not other value than to let me know which key value pair to change in my object
While I'm sure it's possible to use classes that way, it's certainly not their intended purpose. html has data attributes that provide the functionality you want, for example
<button data-key="some value" name="" id="">click me</button>
You can then get that value (onClick if you like) and use it as a key for your object/data structure. Theres a good overview here
While it is not bad, it neither is best practice.
You can, instead of using the class attribute, define explicit data attributes. Using the class attribute would mean that you could not use several classes (because that would be a weird key to search for in an object, right?).
For instance:
<div class="any classes you like" data-mykey="searchforthiskey">
<button></button>
</div>
In jQuery:
$('button').click(function() {
var key = $(this).closest('div').attr('data-mykey');
});
From a functional perspective, there's no reason to NOT use the class attribute to store information about that element. You can access a class attribute as easily as you can a data attribute.
From a standards perspective, it is probably better to use a data attribute. Why? Well, if you are the only person working on your front-end, no big deal. If you are one of many on a team of front-end developers, who works specifically on the javascript side of things, you may run into a conflict with another front-end developer who works on the HTML/CSS side of things. They may remove a class from the element, not realizing that its also being used as your javascript hook into that element. In that case, you're better off creating your own data attribute, which then makes it clear that this attribute is probably data related and won't be molested by someone just trying to fix the styling of that element.

Javascript/Jquery How to catch the use of a CSS class

I am using a Javascript plugin (several lines of code) that from times to times is released a new version.
For this reason I am trying to avoid changing the original source code in order to affect my wishes.
One way that is "half" working for me is to find all the elements that are using a specific CSS class (or group of classes) and them I am removing it (or do something else with them) in order to do what I want.
The part that is not working is the "trigger/event" to process this action. During the execution of this plugin new elements are created and removed and once again I am having "wrong" entries once again.
My question: How can I "catch" all the elements that are "from a moment to the other" using the CSS class XXX? and then execute my own code.
Notes: I was reading the Jquery .on() but I need to specify an event, however the issue is that I do not know the many "places/events" from the original source code are processing this.
Update:
At this point I am "manually" calling my function:
function MyOverrideAction(){
$.each( $( ".sch-gantt-terminal" ), function( key, value ) {
// here I have all my logic.... based on several rules (non relevant to my stackoverflow question)
});
}
I just want that this function is executed every instance when some HTML element is using my target css class.
It is much easier to redefine the CSS class after the original definition. One way to do it is to attach an inline style tag at the bottom of the document which redefines the style. You can use jQuery.append for this. For example see this.
Maybe you search something like this:
https://stackoverflow.com/a/3219767/5035890
If you listen a change in the DOM you can apply all actions that you need. With MutationObserver you can achieve it. Please, consider of the compatibility.
Good luck

Store "templates" of children

I am new to JavaScript so forgive me if the question comes around as dumb.
I know that appendChild() allows me to add a child element to an existing element. However, the problem is that I want to add an element which has an image on the left and a series of text boxes on the right and I need to add it over and over again on button click.
Adding simple elements like p, a , etc can be done by a single call to appendChild(), however for the above scenario, it will be a little messy.
Is there some way that I can define the custom element that I want to append and then just add it with a single call to appendChild()
Are you using jQuery? If it is a really complicated template, you could use .load() to ajax in an template and populate it with whatever you have to. You wouldn't need to dynamically create all of the elements using javascript, only populate it. This would would also allow you to change your template if need be very easily.
It seems you need cloneNode:
target.appendChild(template.cloneNode(true)); // If you want to clone template
// with all its descendants
target.appendChild(template.cloneNode(false)); // If you want to clone template
// without its descendants
I do this quite a bit. My code generally looks like this:
<div class="template" style="display: none;">stuff</div>
then:
$('.template').clone(true).removeClass('template').show().appendTo(someElement);
Since you're not using jQuery, have a look at the clone function here:
http://code.jquery.com/jquery-1.11.0.js
(search for "clone: function" to find it)
You can steal the relevant bits if you can't actually use jQuery itself.

How to get the DOM element that triggered ng-change?

I'm using angularJS. I have a few <select> elements on my page, each with its own ng-change, for example:
<select id="hairColorComponent" ng-model="hairColor"
ng-options="option.name for option in hairColorData"
ng-change="updateUserData()">
I want to be able to determine which DOM element got updated from within the updateUserData function, without having to manually specify it as a parameter for each ng-change attribute.
Is there an event, or caller or something similar that I can use within the context of updateUserData?
Hopefully something like ng-change="updateUserData(caller)"
There's no (easy) way to do this by design. Angular controllers are supposed to be completely separate of the DOM, so if you find yourself needing to reference the DOM in them you're probably approaching things the wrong way.
If your HTML is
<select id="hairColorComponent" ng-model="hairColor"
ng-options="option.name for option in hairColorData"
ng-change="updateUserData()">
Then changing the select will change the value of $scope.hairColor in your controller. In updateUserData() just read its value and act accordingly.
If in your situation there's really no way to do it except referencing the DOM, you could do it by writing a custom directive. In general, direct DOM manipulation in Angular should be a last resort kind of measure though.
Found this on google, I eventually solved my problem so here's my solution.
If you just need the ID, you could always just pass that as a parameter.
<select id="hairColorComponent" ng-model="hairColor"
ng-options="option.name for option in hairColorData"
ng-change="updateUserData('hairColorComponent')">
Still not super clean, but it solved my problem. Since I actually needed the dom element, I then used jQuery to get the element.
$scope.updateUserData = function (id) {
var element = jQuery('#'+id);
};
(For those wondering, I'm doing my best with converting legacy code that "magically" saves user settings on pages all over the website.)

Dynamic class name in Batman.js view

My question is very close to Setting id and className dynamically in Backbone.js views, but for batman.js.
In batman there are data-addclass method, but I need something like this:
<span data-class="item.color"></span>
What will produce for example:
<span class="yellow"></span>
What is the best practice to perform such things in batman.js? Maybe I should use data-bind and detect class with jquery?
The easiest way to do that would be to just perform a data-bind- directly onto the attribute you would like to change, in this case class.
<span data-bind-class="someBatmanVariable">Here is my content</span>
Where someBatmanVariable is just something you've set up in the controller which resolves to the class you'd like the span to have.
You can take it further and put whatever you'd like just about anywhere. You can bind to most attributes and they'll update. Don't forget that by not specifying an attribute (a vanilla data-bind) Batman will default to something logical, usually the contents of the tag or, in the case of input elements, the value.
Finally, be sure to take a look at the Batman view filters. You can massage the output quite a bit.

Categories