lit-html: concatenating strings to use html`` - javascript

I am programming a web-component with lit-element and wonder, how I can render a string inside of a variable which still has intact #click listeners with the html "processor" instead of the pure string.
someFunction() {
var someString=`<button #click="alert('hi')">blah</button>`;
return html([someString]);
}
render() {
return this.someFunction();
}
doesn't work, while
someFunction() {
return html`<button #click="alert('hi')">blah</button>`
}
render() {
return this.someFunction();
}
works.
Thanks for your help!

That is not possible. These are two tagged template literal and function call fundamentally different things:
Tagged template literal
html`<button #click="alert('hi')">blah</button>`
Calling html as a tagged template function will call html function with n-argument parameters. First will be an array of the constant part of the template and arguments from second onwards will be interpolated valued.
Ordinary function call
const someString = `<button #click="alert('hi')">blah</button>`;
html([someString]);
Calling html as a function html([someString]) will call that function with array as its first argument.
Being a language feature, the browser needs to understand a tagged template from ordinary function. It happens at a lexical/syntactical level and thus a tagged function must and must be followed by backtick(`) character.
In summary, tagged function html cannot exist without backtick. You can read more here on MDN docs.

Related

Save JavaScript script text string as function variable to call it

I am fetching a JS script from a server, and getting the following string back:
(function(e){function t(t){for(var r,a,o=t[0],c=t[1] .....
I want to save it as a function variable so I can call it (and pass an argument).
I tried wrapping the string with a return (as suggested here) and then use Function() constructor to call it in order get the original function, but it returns undefined.
How can I do this?
Did you try eval https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/eval
eval is a function that evaluates even if it is a function in string
something like this
const yourVariable = eval("function fromServerResponse(){console.log('executed');}")

Variables As Arguments To Tag Functions

Is it possible to create a tag function when the template literal is a variable?
e.g. instead of this
render`<h1>Hello World</h1>`
Is there any way to do this?
const template = `<h1>Hello World</h1>`
render(template)
No, that's not possible. Tagged templates are a special syntax where render will get called with a string array and all the ${value} values. By storing it in a variable like that, the template literal is instead interpreted as a regular template literal to be converted to a string instead of a function call.
Of course, if all your render function does is concatenation of the template and its variables, it doesn't matter. But mind that the variables inside the template literal are already evaluated when you store it in a variable, it can't get re-evaluated later.

How can I generate a unique JavaScript variable name from a JSF clientId?

I want to define a JavaScript function for every instance of a JSF composite component.
For this, inside the component, I'm trying something like:
<h:outputScript>
function myFunction_#{component.clientId}(day) {
//do my instance specific stuff
}
</h:outputScript>
Specifically I am trying to use this function in a RichFaces calendar like this:
<rich:calendar id="calendar" ... dayClassFunction="myFunction_#{component.clientId}">
But the clientId doesn't necessarily only contain characters which are valid in JavaScript variable names.
Is there a way to calculate an md5 hash or something similarly pseudo-unique from the clientId (or something else!) inside a JSF EL expression?
I need it instance-specific because the return value relies on the instance values and the dayClassFunction attribute doesn't accept a function that takes the clientId itself or something likewise specific as an argument.
I've done it before like this:
window['#{cc.clientId}'] = {
myFunction1 : function() { ... },
myFunction2 : function() { ... }
};
then simply call it where you need it with
dayClassFunction="window['#{cc.clientId}'].myFunction1()"
This way everything is scoped to your component. Eventually you can add some prefix to the client id to never get into conflict with other variable names on the window scope.
Can't think of any character, which is allowed in a client id, that would break the javascript.
Assuming it's the separator (:) that's the issue you could use fn:replace:
function myFunction_#{fn:replace(component.clientId, ':', '_')}
When calling your function, JSF will assign this to be the instance-specific JS object which JSF uses to implement the client side. You may be able to get the information you need from that.

AngularJs & Javascript nested functions & their invocation

Consider the following code
<body ng-app="myApp">
<h1>Hello {{name}}</h1>
<h2>reverse of your name is {{ name | reverse }}</h2>
<input type="text" ng-model="name">
<script src='https://ajax.googleapis.com/ajax/libs/angularjs/1.2.3/angular.js'></script>
<script>
angular.module('myApp', [])
.filter('reverse', function(){
return function(str){
return str.split('').reverse().join('');
}
});
</script>
</body>
The interested bit here is the reverse filter. Here is what I think its doing:
calls angular.filter() with two args. arg1: string & arg2: function(anonymous or no-name function to be precise)
arg2 function doesn't take a argument and instead nested another anonymous function inside it.
This nested anonymous function does takes single argument - the text or string on which this filter would apply.
this nested anonymous function takes the string, reverses it.
Q1. Is my understanding correct?
Q2. What the difference between:
normal version:
angular.filter('reverse', function(str){
return str.split('').reverse().join('');
});
nested version:
angular.filter('reverse', function(str){
return function(str){
return str.split('').reverse().join('');
}
});
Q3. Why is extra level of function nesting useful & under what circumstances will I return the value directly. Or return a function which then does return the actuall result?
Q4. How does this affects scope? does closures have any role to play here?
JSFiddle: http://jsfiddle.net/C7EDv/
(Q1.1) Right- two args, a string with the name of the filter and...
(Q2/3) The second parameter to filter (arg2) is a constructor (or "factory") function. It is only executed once upon creation of the filter.
The constructor function must return a function. That returned function will be executed when the filter it is associated with is used. Put another way, the returned function is what is injected (using $injector) in to the filter (http://docs.angularjs.org/api/ng.$filterProvider)
I've added comments below detailing this:
angular.filter('reverse', function(service){
// This is run only once- upon creation
return function(str){
// This is run every time the filter is called
return str.split('').reverse().join('');
}
});
(Q3) You'll always use this form ("the nested form") otherwise you'll get an error (Object ... has no method 'apply') as Angular needs a function to be returned which it can call (using apply()) whenever the filter is used. This works exactly like all providers in Angular including services.
(Q2) Were it possible to do what you called the "normal version" then the filter would run only once, upon creation. And whatever return value it got would be used for every invocation of the filter. Since having a filter that always returns the same value wouldn't be useful very often Angular instead uses this javascript constructor pattern (which you'll see used elsewhere in JS) so that each use of the filter results in a new invocation of the associated function.
(Q1.4)Yes, the returned function does reverse the string. Here's a nice 2 minute video on exactly this filter: http://www.thinkster.io/pick/EnA7rkqH82/angularjs-filters
(Q1.2/3)Should your filter use any services you'd pass them in where I used service above (the above link has an example of that). The parameter str is the input to the filter like you noted.
(Q4) The "run once" area does create a closure- so you can use it like you would any other closure.

javascript $ followed by curly braces

I read a book called "Javascript web application" and it has the following lines of code:
The example below, which includes logic inside views, is something you shouldn’t do:
<div>
<script>
function formatDate(date) {
/* ... */
};
</script>
${ formatDate(this.date) }
</div>
I don't understand what { formatDate(this.date) } means in javascript even in jQuery I have never seen it yet (putting object in jQuery function then I've already seen but the above code is not the case).
Could you explain me what the meaning of it?
Thank you.
${} is a Template Tag, used by jQuery Template Plugin.
${} Template Tag
Used for insertion of data values in the rendered
template. Evaluates the specified field (property) on the current data
item, or the specified JavaScript function or expression.
It's actually a bit more than this: Indeed, the jQuery Template Plugin used to have this syntax ${}. However, currently, this is part of the ES 6 (aka EcmaScript 2015) standard.
Reference: http://exploringjs.com/es6/ch_template-literals.html

Categories

Resources