Passing variable from jade to ng-init not working - node.js

I'm trying to pass an object from jade to ng-init in angular
This: doesn't work:
ng-init='tables=!{JSON.stringify(tables)}'
This: expands but,
ng-init='tables=#{JSON.stringify(tables)}'
the output is unescaped and filled with "s
ng-init="tables={"12":{"id":....
and the view isn't updated in either of the cases. This article implies that first one should work, but like I said, it doesn't even expand,
ng-init='tables=!{JSON.stringify(tables)}'
in source code shows up exactly the same in the HTML source
ng-init='tables=!{JSON.stringify(tables)}'

Actually, the #{...} approach seems to work fine.
It is probably the way console.log prints attributes' values that confused you.
ng-init="tables=#{JSON.stringify(tables)}"
Take a look at this short demo.

In what use-case you want to pass data directly from Jade to angular? I think you could to this job in controller like this :
$scope.init = function () {
// init stuff
}
...and in your view :
ng-init = init()

Related

Interpolating values in HTML attributes - Pug (Jade)

I am trying to construct an anchor tag with a dynamic href attribute in Jade.
I did go through the docs and some SO questions but they didn't help me. This is what I tried.
a(href= "http://www.imdb.com/title/#{movie.imdb_id}") Know more
But it renders
http://www.imdb.com/title/#{movie.imdb_id}
rather than
http://www.imdb.com/title/tt1234567
However this works
a(href= "http://www.imdb.com/title/" + movie.imdb_id) Know more
and this too.
- var url = "http://www.imdb.com/title/" + movie.imdb_id;
a(href= url) Know more
What's wrong with the first version?
Interpolation is only available in text.
You need to use JS string concatenation for attributes:
a(href="http://www.imdb.com/title/" + movie.imdb_id) Know more
If you JavaScript runtime supports ES2015 template string, you can also use them (notice the backticks):
a(href=`http://www.imdb.com/title/${movie.imdb_id}`) Know more
Reference
the pug variable declaration doesnt work in this case using #{...}
the right syntax goes this way,
a(attributes) Know more
a(href="http://www.imdb.com/title/"+ movie.imdb_id) Know more
the attributes is an expression so it renders correcly, or you could use ES5 template literals with back quotes to render the variable along side the text which becomes
a(href=`http://www.imdb.com/title/${movie.imdb_id}`) Know more
note that when using back quotes with template literals your variable expression are enclosed in parenthesis and a leading $ sign, that is ${..expression..}
When you quote it simply tells pug "this is a string". That's basic JS. Interpolation works with #{'#{interpolation}'} too! is an example which renders "Interpolation works with #{interpolation} too!"
I don't have any knowledge about pug(jade)
But my guess is "a(your code)" is already a signal to pug(jade) that it is in the controller's scope already.. and "{variable}" is also an indicator that you are accessing controller's scope. so
a(href= "http://www.imdb.com/title/#{movie.imdb_id}") Know more
for "{}" inside a() is no longer an indicator that your are trying to access controller's scope because you're already in the controller's scope.. so "{}" inside a() is just a string, {movie.imdb_id} is part of the link string.
So in order for the framework to identity that movie.imdb_id is a variable, you should separate it from the actual string.
NOTE: This is just a guess..I'm using angular

Equality operator in Jade

I am trying to write a mixin in Jade. I would like to pass a parameter through mixin to build same type of block with different value at different states. In the mixin I want to write a conditional that checks if passed parameter is equal to some value. But unfortunately it is not working and I can't find proper documentation anywhere. My code section is following:
mixin test(id)
if territoryList
each val in territoryList
- if (val.parentArea==id){
button.btn.btn-primary.btn-block=val.name
- }
And I am calling it like test('1')
What is the problem?
I don't think your if is supposed to be a javascript if.
Don't you want this ?
mixin test(id)
if territoryList
each val in territoryList
if val.parentArea==id
button.btn.btn-primary.btn-block= val.name

Replacing external scripts with Greasemonkey

A web page uses an external script:
<script src="script/alerts.js" type="text/javascript"></script>
In this script file there is a function which I would like to modify/replace.
The function looks like this:
function SayHello(msg1, msg2){
alert(msg1);
alert(msg2;
// just saying hi and doing something i don't want to
}
I want to change it into something like this:
function SayHello(msg1, msg2){
// not saying hello
// but i'm doing everything i want to
}
How can i do this without using unsafeWindow?
Note: the function must be executed in the content page scope, rather than in the Greasemonkey sandbox.
As simple as that:
location.assign("javascript:void(SayHello = function () {})");
It works even if you need to use any GM_* function. (#grant)
you cannot do something against unsafeWindow unless you run your code within the unsafe window.
what you can do however is redefining the method like:
SayHello = function (msg1, msg2){
// not saying hello
// but i'm doing everything i want to
}
it will replace the original function with this one.
you should also keep in mind that you cannot break into closures just using greasemonkey and that you cannot replace methods that have been copied into local variables the moment the script first ran through.

embedded coffeescript in a coffeekup view in zappa

Is there a way to pass variable values (just for reading, obviously) from the app to the embedded coffeescript in a coffeekup view (in zappa), such as:
.... #render 'index', myVar:"something"
#view index: ->
coffeescript ->
$(document).ready ->
I need to get to myVar here...
It seems really slick if it would work... (as an alternative to embedded javascript)
Update: Here are a few attempts. I'm just trying to use the string in my embedded script as an id.
coffeescript ->
$(document).ready ->
id = myVar
coffeescript ->
$(document).ready ->
id = "#{myVar}"
coffeescript ->
$(document).ready ->
id = #myVar
coffeescript ->
$(document).ready ->
id = "#{#myVar}"
I've written some quick javascript in a script -> function (since it's just a string, I can interpolate the variables easily), so I've worked around it, but the coffeescript way would be cleaner. It makes sense that the scope would be lost on the browser side--I was just trying to figure out how to do it.
I guess by "script -> function", you mean something like:
doctype 5
html ->
body ->
h1 "Hello world."
script "myvar = \"#{#myvar}\""
coffeescript ->
console.log myvar
At least that's a hackish workaround. It could be done with objects as well, typically using JSON or similar for serialization.
But I would not categorize this as a "clean coffeescript way", so I guess the question still stands!
Just to elaborate a bit; The problem here is that we're executing coffeescript code in two contexts; one on the server which generates the html to send to the client, and the other on the client itself through in the context of the coffeescript -> construct.
The server side knows about locals and similar, so for the code that runs on the server, it's simple to evaluate the coffeescript based template and replace template variables with values and similar.
Not so on the client. First of all the client knows nothing about locals / template variables, it only sees whatever those contained when the page got rendered server side. And doing simple template expansion inside the coffeescript construct would not work either, as coffeescript would not know if you refer to a local variable on the client or a template variable on the server. In theory there could be special sequences that signal "expand template variable inside coffeescript code" as well, but then we're just - again - creating a new template language on top of coffeecup. It could be made to look like regular coffeescript of course, e.g. serverLocal(SOMEREF), where SOMEREF would be replaced with the corresponding value.
In theory, Coffeecup could support a construct that shared all (or a selection of) locals also as variables to be accessed client side, using a "hack" similar to the script hack I showed above, and it would probably be not too different, except using JSON or similar for supporting more kinds of data than simple strings.

Is there any fast tool which performs constant substitution without stripping out comments in JavaScript source code?

For example, setting MYCONST = true would lead to the transformation of
if (MYCONST) {
console.log('MYCONST IS TRUE!'); // print important message
}
to
if (true) {
console.log('MYCONST IS TRUE!'); // print important message
}
This tool ideally has a fast node.js accessible API.
A better way to achieve what you want -
Settings.js
settings = {
MYCONST = true
};
MainCode.js
if (settings.MYCONST) {
console.log('MYCONST IS TRUE!'); // print important message
}
This way, you make a change to one single file.
google's closure compiler does, among other things, inlining of constants when annotated as such, leaving string content untouched but I am not sure if it's a viable option for you.
Patch a beautifier, for example
Get the JS Beautifier https://raw.github.com/einars/js-beautify/master/beautify.js written in JS.
Replace the last line of function print_token() by something like
output.push(token_text=="MYCONST"?"true":token_text);
Call js_beautify(your_code) from within nodejs.
The Apache Ant build system supports a replace task that could be used to achieve this.
Edit: Whoops. Gotta read title first. Ignore me.
Google Closure Compiler has such a feature:
You can combine the #define tag in your code with the --define parameter to change variables at "compile" time.
The closure compiler will also remove your if-statement, which is probably what you want.
Simply write your code like this:
/** #define {boolean} */
var MYCONST = false; // default value is necessary here
if (MYCONST) {
console.log('MYCONST IS TRUE!'); // print important message
}
And call the compiler with the parameter:
java -jar closure-compiler.jar --define=MYCONST=true --js pathto/file.js
Regarding you API request: Closure Compiler has a JSON API.

Resources