I am creating an application where the site menu would be dynamically loaded from JSON file. Each menu may correspond to an action that would be defined inside the ng-click directive. This would look something like this
<li ng-repeat="menuItem in menuContainer.menus" class="{{menuItem.cssClass}}">
<a href="{{menuItem.url}}" ng-click="{{menuItem.clickAction}}">
<i class="{{menuItem.iconClass}}"></i>{{menuItem.name}}
<span class="badge">{{menuItem.subMenus.length}}</span>
</a>`enter code here`
<li>
Now the problem is ng-click does not recognize the clickAction as a function, I believe this is due to linking process. I want to know is there any way to evaluate a string to method. I tried do $eval but it executes the function on load.
How do I do this?
Define methods not as strings, but as functions and replace ng-click="{{menuItem.clickAction}}" to ng-click="menuItem.clickAction()". Another way to define function on $scope, like:
$scope.executeString = function(body){
eval(body);
};
and replace your ng-click to ng-click="executeString(menuItem.clickAction)". Anyway, use eval is antipattern;)
Remember, that ng-click and other directives, like that, takes angular expression as parameter. And if body of you expression is a = b + c than angular convert it in javascript like $scope.a = $scope.b + $scope.c
Related
A question of coding haskell with good form, instead of 'it works'.
We want our menu navigation items to have a highlighted CSS class when the user is on that page.
Easy.
Here are my routes:
...
/simple SimpleR GET POST
/search SearchFormR GET POST
/searchresults/#Int/#Text SearchResultsR GET
...
In my hamlet template I have the below. This works perfectly, the link is highlighted when the user is on that page. The route is simple.
<li .nav-item>
<a .nav-link :Just SimpleR == mcurrentRoute:.active href=#{SimpleR}>
Simple page
This link should be highlighted when the user is on either of SearchFormR or SearchResultsR.
<li .nav-item>
<a .nav-link :((Just (SearchResultsR _ _)) == mcurrentRoute) || (Just SearchFormR == mcurrentRoute):.active href=#{SearchFormR}>
Search
This code does not work, because the SearchResultsR route constructor needs the two things passed to it. I cannot write _ _ as I have above, since the constructor needs a literal value. And besides, the result of the constructor will be compared with == to the actual route anyway, it won't match unless both parameters happen to be the exact same.
Without the _ _ I of course get a type error, expecting two more things passed to the SearchResultsR constructor.
That is, I want to check if we are on any SearchResultsR route, not only match SearchResultsR 123 "abc".
My first thought was to make a function to convert the route to a string and then check if that string contains the string of the route, but this is bad, and not the haskell / typesafe way.
My second attempt is using pattern matching:
Foundation.hs:
isThisRouteSearchResultsR :: Maybe (Route App) -> Bool
isThisRouteSearchResultsR (Just (SearchResultsR _ _)) = True
isThisRouteSearchResultsR _ = False
Hamlet template:
<li .nav-item>
<a .nav-link :(isThisRouteSearchResultsR mcurrentRoute) || (Just SearchR == mcurrentRoute) :.active href=#{SearchR}>
Search
But this doesn't seem much better. What if I have a lot more routes that have dynamic parts?
What is the proper way to do this? I looked at haskellers site source code but couldn't find the answer
The answer given by Sibi in the comments (thank you Sibi) is that the second approach in the question is in good form / style.
e.g. in hamlet:
:(isThisRouteSearchResultsROrSearchR mcurrentRoute) :.active
Or could do
:(isThisRouteSearchResultsR mcurrentRoute) || (isThisRouteSearchR mcurrentRoute) :.active
And you define these functions in Foundation.hs (Haskell) as per the question code.
Sibi:
The goal is to usually keep all your logic in the Haskell file and
keep it minimal in the Hamlet file.
Thank you Sibi for your guidance.
I want to programatically modify the color of variables. I have attempted with this
<p> \(\overline{<font color="#0000EE" id="test_A">A</font>+B}+\overline{B}\)</p>
But it will just break the syntax. I can't break the equation into multiple equations due to it being nested within an overline.
Any tips on adding an identifier to a mathjax variable so I can refer to it within javascript?
Write css class rules instead, then \class{yourClass}{yourVariable} :
.yourClass{
color:#0000EE;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-AMS_CHTML-full"></script>
<p> \(\overline{\class{yourClass}{A}+B}+\overline{B}\)</p>
You now have an 'identifier' for your variable, once it's processed, you can easyly change color with javascript
var button = document.querySelector('button');
button.addEventListener('click',changeColor);
function changeColor(){
document.querySelector('.yourClass').style.color='red';
}
.yourClass{
color:#0000EE;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/mathjax/2.7.5/MathJax.js?config=TeX-AMS_CHTML-full"></script>
<p> \(\overline{\class{yourClass}{A}+B}+\overline{B}\)</p>
<button>click</button>
We use this syntax to include partial during run time:
{{> (lookup . 'file') }}
file is a var name from the parent file.
I tried to add a prefix to the file name, So I tried:
{{> lookup . 'path/file'}}
{{> (lookup . (strmerge 'path/' 'file')) }}
Note: I made a helper method to merge strings
I tried those and others but nothing worked for me.
Does any one know how to do this?
Thanks
In the code {{> (lookup . 'file') }} we are telling Handlebars that the name of our partial is to be found at the file property of the current context object.
Assuming a context object like { file: 'myPartial' }, the result of the lookup is {{> myPartial }}, which tells Handlebars to render a partial called "myPartial".
If we want to add a prefix to our partial, so that Handlebars will register a partial called "path/myPartial", the simplest way to do this would be to add that path to the value of the file property in the context object. The context object would become: { file: 'path/myPartial' }.
If, for some reason, the "path/" prefix must be added to the template and not the data, then we will need to determine a way to produce the String "path/myPartial" from our current data.
Both of your attempts put "file" in the name of the property to be looked-up. Your code will try to find the property path/file on the context object and this will fail. We will definitely need a helper to concatenate Strings, but it must concatenate "path/" with the value of file, not the literal String, "file".
To achieve our goal we will no longer require the lookup helper. The lookup was needed only because you can't write {{> (file) }} in Handlebars, because Handlebars will treat file as a helper instead of as a variable. However, since we are using a concatenation helper, strmerge, we can use the String it returns as our partial name, without any need for a lookup. The correct code becomes:
{{> (strmerge 'path/' file) }}
It's important to note that file in this example is not in quotes. It is a variable, not a String.
I have created a fiddle for your reference.
How to change the font color of Hello alone in "Hello World" using javascript/some other method?
I tried the following code,
var s= session.getCommonUserName()
s.fontcolor("green")
"Hello"+" "+ s.toUpperCase()
where i tried to change just the color of the username alone. But it failed.
I wouldn't bother to send down unformatted HTML to the client and then let the client do the JavaScript work. You create a computed field and give it the data type HTML (that keeps HTML you create intact) and use SSJS. So no JS needs to execute at the client side:
var cu = session.getCommonUserName();
return "Hello"+" <span style=\"color : green\">"+ cu.toUpperCase()+"</span>";
Don't forget to cross your t, dot your i and finish a statement with a semicolon :-)
If you want to do it with client java script, then you must do something like this:
dojo.style("html_element_id", "color", "green");
So in your case you can have have something like:
<p><span id="span1">Hello</span> World.</p>
Or you can do it directly if you don't need to change it with CJS:
<p><span style="color:green">Hello</span> World</p>
one way to do it is to wrap your 'hello' in a html span and then change the color of that span.
<span id='myspan'>hello</span> world
javascript code:
document.getElementById('myspan').style.color='green';
Went old school on this one...
Say you want to put your formatted text in a div
<div id="test">
</div>
Then you need the following javascript to do so:
div = document.getElementById("test");
hello = document.createElement("span");
hello.innerHTML = "Hello"
hello.style.color = "green";
div.appendChild(hello);
div.appendChild(document.createTextNode(" world!"));
Is there a better way to capitalize the first character of a string in Jade than this?
for list in project.lists
- list.name = list.name.charAt(0).toUpperCase() + list.name.slice(1);
li #{list.name}
Doing this every time I want to capitalize a variable is ugly, is there any way in Jade that I can define a custom function that I have available in every template like:
for list in project.lists
li #{ucfirst(list.name)}
Thanks in advance!
The contents of #{} are executed as standard JS, so you can pass in helper functions for use with things like that. You haven't specified, but assuming you are using Jade along with Express, you can do something like this:
app.locals.ucfirst = function(value){
return value.charAt(0).toUpperCase() + value.slice(1);
};
That will expose a function called ucfirst within the Jade template. You could also pass it in as part of locals every time you render, but if you are using Express it will do it automatically.
If you're willing to resort to CSS, you can create a class that capitalizes the first letter of every word within the target element.
CSS
.caps {
text-transform: capitalize;
}
Jade
div.caps
each foo in ['one', 'two', 'three']
span #{foo}
Resulting HTML
<div class="caps"><span>one</span><span>two</span><span>three</span>
Resulting view
One Two Three
If you are using pug with gulp, this can be helpful:
mixin ucfirst(text)
- text = text.charAt(0).toUpperCase() + text.slice(1);
.
#{text}
Simply call this as any other mixin:
li
+ucfirst(list.name)