Kraken, Dust and Makara - dust.js

<span id='sitemap'>
{#footer.sitemaps}
<a id="{id}" href="{url}">{#pre type="content" mode="json" key="footer.{id}"/}</a>
{/footer.sitemaps}
</span>
In the code, {id} is a property of one element in footer.sitemaps. I want Makara to get the key value dynamically using {id}. May I know how to do that?

See the discussion around this makara issue: https://github.com/krakenjs/makara/issues/36

Check this: https://github.com/mikesparr/Kraken_Example_i18n_Helper
You can use #bundleString helper rather than #pre.
So, you can use something like {#bundleString key="footer.{id}" bundle="your_data_properties_file name"}

You can do that by using the {#provide} tag. Here is an example using yours:
{#provide}
{#footer.sitemaps}
<a id="{id}" href="{url}">{footerMap[id]}</a>
{/footer.sitemaps}
{:footerMap}
{#pre type="content" mode="json" key="footer"/}
{/provide}
If your properties file looked like
footer.key1=SomeVal
footer.key2=AnotherVal
and your footer.sitemaps data object looked like
{
id: 'key1',
href: 'http://my/url
}
The result of running this would be
<a id="key1" href="http://my/url">SomeVal</a>

Related

How can I make a conditional statement like "include?" method in Ruby on Angular ng-if

Sorry about the difficulty for me to make the title much clearer. I'll explain as much as I can.
I use Rails as the backend (API), and AngularJS as the frontend.
I got several article_ids that have been liked(thumb up) from articleCtrl, named $scope.article_has_liked (it's an array contains several article_ids, like [24,45,55] ), just like below, :
articleCtrl.js.coffee
$http.get(url).success((data)->
console.log(data)
$scope.articles = data.articles
$scope.topic = data.topic
$scope.article_has_liked = data.article_has_liked
)
And I pass these article_ids ($scope.article_has_liked) to the show.html, in order to use "ng-if" to conduct a judgement, just like below:
Show.html
<div ng-if="article_has_liked.include?(article.id)">
<button class="btn btn-link" ng-click="likeItOrNot(article.id, topic.id)">
<span class="glyphicon glyphicon-star"></span>
</button>
</div>
<div ng-if="article_has_liked.exclude?(article.id)">
<button class="btn btn-link" ng-click="likeItOrNot(article.id, topic.id)">
<span class="glyphicon glyphicon-star-empty"></span>
</button>
</div>
Here comes the problem !
I'd like to use .include? method in Ruby to determine if the article.id is included by the article_ids that have been liked. If it is liked, I'll give it a solid star. But I found that the Angular seems not to accept the usage, and it returned the error just like below:
Error: Syntax Error: Token 'undefined' expected : at column NaN of the expression [article_has_liked.include?(article.id)] starting at [article_has_liked.include?(article.id)].
throwError#http://localhost:3000/assets/angular.self-cdfe10db265380c82ec938d307fce2720dc9fb9d8cfa21c78928031af124e282.js?body=1:6672:1
ternary#http://localhost:3000/assets/angular.self-cdfe10db265380c82ec938d307fce2720dc9fb9d8cfa21c78928031af124e282.js?body=1:6827:9
_assignment#http://localhost:3000/assets/angular.self-cdfe10db265380c82ec938d307fce2720dc9fb9d8cfa21c78928031af124e282.js?body=1:6800:16
expression#http://localhost:3000/assets/angular.self-cdfe10db265380c82ec938d307fce2720dc9fb9d8cfa21c78928031af124e282.js?body=1:6796:12
_filterChain#http://localhost:3000/assets/angular.self-cdfe10db265380c82ec938d307fce2720dc9fb9d8cfa21c78928031af124e282.js?body=1:6762:16
statements#http://localhost:3000/assets/angular.self-cdfe10db265380c82ec938d307fce2720dc9fb9d8cfa21c78928031af124e282.js?body=1:6742:25
parser#http://localhost:3000/assets/angular.self-cdfe10db265380c82ec938d307fce2720dc9fb9d8cfa21c78928031af124e282.js?body=1:6661:13
$ParseProvider/this.$get</<#http://localhost:3000/assets/angular.self-cdfe10db265380c82ec938d307fce2720dc9fb9d8cfa21c78928031af124e282.js?body=1:7282:1
compileToFn#http://localhost:3000/assets/angular.self-cdfe10db265380c82ec938d307fce2720dc9fb9d8cfa21c78928031af124e282.js?body=1:9215:16
$RootScopeProvider/this.$get</Scope.prototype.$watch#http://localhost:3000/assets/angular.self-cdfe10db265380c82ec938d307fce2720dc9fb9d8cfa21c78928031af124e282.js?body=1:8547:19
ngIfDirective</<.compile/<#http://localhost:3000/assets/angular.self-cdfe10db265380c82ec938d307fce2720dc9fb9d8cfa21c78928031af124e282.js?body=1:14677:9
nodeLinkFn#http://localhost:3000/assets/angular.self-cdfe10db265380c82ec938d307fce2720dc9fb9d8cfa21c78928031af124e282.js?body=1:4960:13
compositeLinkFn#http://localhost:3000/assets/angular.self-cdfe10db265380c82ec938d307fce2720dc9fb9d8cfa21c78928031af124e282.js?body=1:4539:15
compositeLinkFn#http://localhost:3000/assets/angular.self-cdfe10db265380c82ec938d307fce2720dc9fb9d8cfa21c78928031af124e282.js?body=1:4554:13
compositeLinkFn#http://localhost:3000/assets/angular.self-cdfe10db265380c82ec938d307fce2720dc9fb9d8cfa21c78928031af124e282.js?body=1:4554:13
compositeLinkFn#http://localhost:3000/assets/angular.self-cdfe10db265380c82ec938d307fce2720dc9fb9d8cfa21c78928031af124e282.js?body=1:4554:13
compositeLinkFn#http://localhost:3000/assets/angular.self-cdfe10db265380c82ec938d307fce2720dc9fb9d8cfa21c78928031af124e282.js?body=1:4554:13
compositeLinkFn#http://localhost:3000/assets/angular.self-cdfe10db265380c82ec938d307fce2720dc9fb9d8cfa21c78928031af124e282.js?body=1:4554:13
publicLinkFn#http://localhost:3000/assets/angular.self-cdfe10db265380c82ec938d307fce2720dc9fb9d8cfa21c78928031af124e282.js?body=1:4456:30
ngRepeatAction#http://localhost:3000/assets/angular.self-cdfe10db265380c82ec938d307fce2720dc9fb9d8cfa21c78928031af124e282.js?body=1:15463:15
$watchCollectionAction#http://localhost:3000/assets/angular.self-cdfe10db265380c82ec938d307fce2720dc9fb9d8cfa21c78928031af124e282.js?body=1:8718:11
$RootScopeProvider/this.$get</Scope.prototype.$digest#http://localhost:3000/assets/angular.self-cdfe10db265380c82ec938d307fce2720dc9fb9d8cfa21c78928031af124e282.js?body=1:8812:21
$RootScopeProvider/this.$get</Scope.prototype.$apply#http://localhost:3000/assets/angular.self-cdfe10db265380c82ec938d307fce2720dc9fb9d8cfa21c78928031af124e282.js?body=1:9013:13
done#http://localhost:3000/assets/angular.self-cdfe10db265380c82ec938d307fce2720dc9fb9d8cfa21c78928031af124e282.js?body=1:10266:34
completeRequest#http://localhost:3000/assets/angular.self-cdfe10db265380c82ec938d307fce2720dc9fb9d8cfa21c78928031af124e282.js?body=1:10450:7
createHttpBackend/</xhr.onreadystatechange#http://localhost:3000/assets/angular.self-cdfe10db265380c82ec938d307fce2720dc9fb9d8cfa21c78928031af124e282.js?body=1:10405:1
<!-- ngIf: article_has_liked.include?(article.id) -->
So I want to ask if there is any conditional statement which has similar meaning to .include? that I can use in AngularJS "ng-if", or there is any better way for me to conduct this judgement?
Thanks everyone for helping me this confusing question!
That is a JavaScript relating question, not AngularJS. But may that answer your question:
Often you will need to check whether an array contains a certain item. You can do this by using the indexOf() method. If the code does not find the item in the list, it returns a -1.
var article_has_liked = [24,45,55];
if(article_has_liked.indexOf(99) == -1){
alert("data not found");
}
Not sure but you can try something:
<div ng-if="article_has_liked.indexOf(article.id) != -1">
Note: This above condition is to check for include. If it include your article.id in article_has_liked then only execute that block. If you want to check exclude then you can simply use == instead != I hope it works for you.
ng-if="article_has_liked.include?(article.id)"
update to this one:
ng-if="article_has_liked.include?(article.id):false value here"

Get children of an XHPChild

I am trying to move my website to Hack and XHP, of course. Below is a structure of what code structure I want to achieve:
<ui:backstageHeader>
<ui:backstageHeader-navItem href="/">stories</ui:backstageHeader-navItem>
<ui:backstageHeader-navItem href="/story/send">send a story</ui:backstageHeader-navItem>
<ui:backstageHeader-navItem href="/aboutus">support</ui:backstageHeader-navItem>
</ui:backstageHeader>
(Note: :ui:backstageHeader-navItem basically renders to <a href={$this->:href}>{$this->getCHildren}</a> so there is not need to attach its class here.)
Below is the code for :ui:backstageHeader:
final class :ui:backstageHeader extends :ui:base {
attribute :div;
children (:ui:backstageHeader-navItem)*;
protected function compose() {
$dom =
<section class="backstage-header">
<div class="container">
<div class="cell-logo">
<a href="/">
<span class="no23-logo-white"></span>
</a>
</div>
<div class="cell-navigation">
</div>
<div class="cell-account">
<div class="cell-login">
<div id="siteNav-login">Autentificare</div>
</div>
</div>
</div>
</section>;
$mainContainer = $dom->getChildren("div")[0];
$cellNavigation = $mainContainer->getChildren("div")[1];
$navItems = <ul class="main-navigation"></ul>;
foreach($this->getChildren() as $child) {
$navItems->appendChild(<li>{$child}</li>);
}
$dom->appendChild($navItems);
return $dom;
}
}
I used the Terminal to debug my code using hhvm -m d <file.php>, and everything was alright there; however, when I get to my browser, I get 500 error header. This is what the log says:
Catchable fatal error: Hack type error: Could not find method getChildren in an object of type XHPChild at /var/www/res/ui/backstage-header.php line 25
The error comes from
$cellNavigation = $mainContainer->getChildren("div")[1];
But, somehow, I need to append ul.main-navigation to div.cell-navigation from my section.backstage-header.
How can I do it?
Don't structure your code this way. Built it up from the inside out, so that you don't have to do a ton of unreadable getChildren calls looking for specific children. Those calls are super hard to read, and super inflexible when you change the structure of your XHP. You wouldn't do something like node.firstChild.lastChild.lastChild.firstChild in the JS DOM, would you? No, there's a better way in JS, to find things by class or ID; in XHP, you can just build it up the right way in the first place!
I'd give you an example of this, but it doesn't look like you actually use $mainContainer or $cellNavigation, so you can just remove those two problematic definitions.
As an aside, you really shouldn't be getting your type errors as catchable fatals from HHVM; this is a last resort sort of check. Try running the hh_client checker directly, maybe even showing its result in your IDE; it will give you a much faster iteration cycle, and much more information than HHVM provides.
From my experience, appendChild is very prone to human error. It's easier to do something like:
$items = (new Vector($this->getChildren()))->map($child ==> <li>{$child}</li>);
return <div id="container">{$items}</div>;
If you want to wrap the children in <li />.
Not sure if that will work but it will be close.
Pro tip: You can assign variables from within an XHP tree.
$root =
<div>
{$child = <span>
Text children
</span>}
</div>;
Now $child is already set to the <span> element.

Getting issue to generate Absolute Url's in MVC

Hi I have created a mvc website which is working fine with localhost if i am coding something like this:
<base href="http://localhost:5400/" />
<li><a class="home" href="/Home/Index/">Home</a></li>
<li class="wish"><a class="wishlist" href="/Products/Index/" id="wishlist-total">Products</a></li>
<li><a class="account" href="/Home/Contact/">Contact Us</a></li>
But now to run it on live if i am trying to changing this:
<base href="http://localhost:5400/" />
with this:
<base href="HttpContext.Current.Request.Url" />
then its actually taking full root url everytime.So whenever i am clicking on any menu and moves to next menu it regain previous menu path also.
For this issue i tried below code which is also not working.
<li>Home</li>
<li>Products</li>
<li> Contact</li>
According me this code will work,But if i am trying to pass "null" as third parameter then i gives error:
ERROR: 'null' is not declared. 'Null' constant is no longer supported; use 'System.DBNull' instead.
Can someone please suggest what i should need to change?
Thanks
Quick fix...
#Url.Action("Index", "Home")
There's no need to enter null as a parameter... if you want to indicate that a parameter can be null, then you need to define that in the route its self, and if the parameter is missing, then it will know that the value is null implicitly...
// http://yoursite/Example/{id}
[Route("~/Example/{id}"] // Can't be null
public ActionResult Example(string id){ return View(); }
// http://yoursite/ExampleTwo/
[Route("~/ExampleTwo/{id?} // Can be null
public ActionResult ExampleTwo(string id) { return View(); }
TLDR if you want more errors...
Your issue is actually indicating a much larger issue... it looks as if you're accepting a query from a URI directly into a SQL query... if you are doing that, you're opening yourself up to injection attacks and as much as a part of me feels that anyone who does that pretty much has it coming to them... I can't stand by and just say nothing... sanitize any data that you receive from the user, no matter where it's coming from, example
Remove all those magic strings... you shouldn't have any strings such as the one you just displayed...
// Bad...
<a class="home" href="/Home/Index/">
// Better...
<a class="home" href="#Url.Action("Index", "Home")">Home</a>
// Good
#Html.ActionLink("Home", "Index", "Home")

Grails - Pass JSON/Map object to client

I am trying to save a JSON object to a data- field in a gsp page.
Mock controller:
def test(){
['comments': ["1": 1, "3":40 ] ]
}
GSP (I also tried (comments as JSON) )
<%# page import="grails.converters.JSON" %>
<div class='findme' data-comments="${comments as JSON}">
Result:
<div class='findme' data-comments="{" 1":1,"3":40}">
As you can see the quotes are all messed up. I tried using encodeAsHTML but it didn't work.
I ran into this recently as well and came up with two solutions:
Solution One: in the template do this:
<div class="comments" data-comments="${comments.encodeAsJSON().encodeAsHTML()}">
Solution Two: in the controller do this:
def test(){
['comments': ["1": 1, "3":40 ] as JSON]
}
and in the template do this:
<div class="comments" data-comments="${comments.encodeAsHTML()}">
I'm using jQuery to do the parsing. With either solution I get the JSON like so:
$.parseJSON($('.comments').attr('data-comments'));
I found a couple ways to do it.
<div class='findme' data-comments="${(new JSON(comments)).toString().encodeAsURL()}">
Then I have to pull it out like:
JSON.parse(unescape($('.findme').data('comments')))
Found another way to do it, but it will cause problems if you have anything that has a " in it. I think encoding it is the way to go.
${(comments as JSON).toString().replace("\"", "'")}
I have found an easy way to do that.
First you do:
<div class="comments" data-comments="${comments.encodeAsJSON()}">
And then in javascript:
eval($('.comments').attr('data-comments'));

Wicket link - is adding a label necessary to set the text?

Currently, I do this:
<li><a wicket:id="link" href="#"><span wicket:id="name">jawa01</span></a></li>
and
item.add( new BookmarkablePageLink("link", ResourcePage.class)
.setParameter("name", item.getModelObject().getName())
.add( new Label("name", item.getModelObject().getName()) )
);
I want to do ommit the element:
<li><a wicket:id="link" href="#">...</a></li>
How should the java code look?
I expect something like
item.add( new BookmarkablePageLinkWithLabel(
"link", ResourcePage.class, item.getModelObject().getName())
.setParameter("name", item.getModelObject().getName())
);
Thanks, Ondra
This is not built into Wicket, with a couple of reasons presented here.
However, you can certainly make you own component out of what you currently do to make your life easier. The constructor would take both the model for the link and the model for the label.

Resources