Accessing hashes in Perl templates - html

How do you access variables in a hash when using Perl's HTML::Template module?
I'm building the following hash in my Perl code:
# Load success/error flash messages
if ($query->param("submit")) {
$template->param(
FLASH => {
CLASS => "success",
MESSAGE => "Your cart has been successfully updated!"
}
);
}
I'd like to access these variables in my template. To access a regular variable, you do:
<TMPL_VAR NAME=FLASH>
How might I access FLASH['CLASS'] in my template?

Access with a . (dot)
FLASH.CLASS

There's nothing in the documentation that indicates you can set a parameter as a hashref. The closest to what you want to do is to put the hashref in an arrayref:
$template->param(
FLASH => [ {
CLASS => "success",
MESSAGE => "Your cart has been successfully updated!"
} ]
);
Then you can access it as:
<TMPL_LOOP NAME=FLASH>
<TMPL_VAR NAME=CLASS>
<TMPL_VAR NAME=MESSAGE>
</TMPL_LOOP>
But having an array with a single element might be overkill. An alternative is to get rid of the hashref and flatten the structure:
$template->param(
FLASH.CLASS => "success",
FLASH.MESSAGE => "Your cart has been successfully updated!"
);
...
<TMPL_VAR NAME=FLASH.CLASS>
<TMPL_VAR NAME=FLASH.MESSAGE>

HTML::Template always needs a hash of arrays of hash of arrays and so on.
If you have an arbitrary data structure you might want to try HTML::Template::Compiled where you can use the dot syntax (disclaimer: I'm the author)
There is also HTML::Template::Plugin::Dot but I have never tested it and it seems to be a bit more limited.

Related

How to type function's return to be an array of instances of a dynamic class via .phpstorm.meta.php file?

With .phpstorm.meta.php you can overwrite the return type of your class methods. For example:
// .phpstorm.meta.php
namespace PHPSTORM_META
{
$STATIC_METHOD_TYPES = [
\Acme\Node::closest('') => [
"" == "#",
],
];
}
The example above lets PhpStorm understand the return of $node->closest(SomeNodeType::class) is an instance of SomeNodeType.
However, my question is how to make PhpStorm understand that a function returns an array of instances of a given type.
For example:
$node->findAllOfType(SomeNodeType::class) would return an array of SomeNodeType instances (normally one would use SomeNodeType[] if it would not be dynamic).
Attempts to use "#[]" or "#Iterator" instead of "#", in the above code example, failed.
That's simply not supported ... unless you can try and list all possible types manually instead of using single generic rule (which may work in theory -- sorry, have not tried it myself).
https://youtrack.jetbrains.com/issue/WI-27832 -- watch that and related tickets (star/vote/comment) to get notified on any progress.

Angular 4 html for loop displaying loosely typed object (string) normally but not when element is extracted directly?

I'm using Angular 4 to develop an app which is mainly about displaying data from DB and CRUD.
Long story short I found that in Angular 4 the component html doesn't like displaying loosely typed object (leaving the space blank while displaying other things like normal with no warning or error given in console) even if it can be easily displayed in console.log output, as shown in a string.
So I made a function in the service file to cast the values into a set structure indicating they're strings.
So now something like this works:
HTML
...
<div>{{something.value}}</div>
...
Component.ts
...
ngOnInit() {
this.route.params.subscribe(params => {
this.pkey = params['pkey'];
this.service.getSomethingById(this.pkey)
.then(
something => {
this.something = this.service.convertToStructure(something);
},
error => this.errorMessage = <any>error);
});
}
...
Code of the function convertToStructure(something)
convertToStructure(someArr: myStructure): myStructure {
let something: myStructure = new myStructure();
something.value = someArr[0].value;
return something;
}
But as I dig into other files for copy and paste and learn skills from what my partner worked (we're both new to Angular) I found that he did NOT cast the said values into a fixed structure.
He thought my problem on not being able to display the values (before I solved the problem) was because of me not realizing it was not a plain JSON object {...} but an array with a single element containing the object [{...}] .
He only solved half of my problem, cause adding [0] in html/component.ts was not able to make it work.
Component.ts when it did NOT work
...
ngOnInit() {
this.route.params.subscribe(params => {
this.pkey = params['pkey'];
this.service.getSomethingById(this.pkey)
.then(
something => {
console.log(something[0].value); //"the value"
this.something = something[0]; //html can't find its value
},
error => this.errorMessage = <any>error);
});
}
...
HTML when it did NOT work
...
<div>{{something[0].value}}</div> <!--Gives error on the debug console saying can't find 'value' of undefined-->
...
And of course when I'm using the failed HTML I only used this.something = something instead of putting in the [0], and vice versa.
So I looked into his code in some other page that display similar data, and I found that he used *ngFor in html to extract the data and what surprised me is that his html WORKED even if both of our original data from the promise is identical (using the same service to get the same object from sever).
Here's what he did in html:
...
<div *ngFor="let obj of objArr" ... >
{{obj.value}}
</div>
...
His html worked.
I'm not sure what happened, both of us are using a raw response from the same service promise but using for loop in html makes it automatically treat the value as strings while me trying to simply inject the value fails even if console.log shows a double quoted string.
What's the difference between having the for loop and not having any for loop but injecting the variable into html directly?
Why didn't he have to tell Angular to use the set structure indicating the values are strings while me having to do all the trouble to let html knows it's but a string?
The difference here is as you said that your JSON is not simple object , its JSON Array and to display data from JSON array you need loop. So, that is why your friends code worked and yours did not. And please also add JSON as well.

$.post(url, data) doesn't work

I'm creating simple twitter_clone using Rails to create json API and ReactJS in frontend.
What I need now is to save new created tweet into DB and then to update an API in json which contain list of tweets to be able to use them to render a view.
To achieve it I try to use post request:
My add tweet function in main.jsx file
addTweet(tweetToAdd){
$.post("/tweets", { body: tweetToAdd }) //after saving to database
.success( savedTweet => {
let newTweetsList = this.state.tweetsList;
newTweetsList.unshift(savedTweet);
this.setState({tweetsList: newTweetsList});
})
.error(error => console.log(error));
}
There is a problem with delivering body of the tweet to database, cause after submitting there is NULL here.
Probably it means that body isn't send to DB ,but rest of parameters there are.
in /tweets there is an json API which looks like:
[{"id":17,"user_id":1,"body":null,"created_at":"2015-12-18T10:11:25.085Z","updated_at":"2015-12-18T10:11:25.085Z","name":"Marek Czyż"}]
When I create tweet manually form console everything works. so the problem must have been in previous piece of code.
Secondly after pressing SUBMIT tweet Ive recevied a warning that
Warning: Each child in an array or iterator should have a unique "key" prop. Check the render method of TweetList. See fb.me/react-warning-keys for more information.
although Ive got a key to every Tweet:
let tweets = this.props.tweets.map(tweet => );
Please, help me.
Assuming you're passing the right value as tweetToAdd, make sure you permit the body param in your controller. If it works in the console, it's not a validation problem, rather an unpermitted param.
As for the error you're seeing, you'll need to add a key prop to each rendered tweet. Something like:
render() {
let tweets = this.props.tweets;
return <ul>
{tweets.map(tweet => {
return <li key={tweet.id}>{tweet.body}</li>;
})}
</ul>;
}

MediaWiki API Extension JSON

I have developed a MediaWiki extension that gets a (JSON) string from an external service using cURL.
Now I'm looking for a way to retrieve just that string from the MediaWiki system. (This URL will be used for AJAX calls.)
First, I thought that MediaWiki API was the way to do that. However, I can't seem to be able to output just that string.
What would be the right way to achieve this?
UPDATE
Thank you, that did the trick. For your information, here's how far I got:
$this->getResult()->addValue(null, null, array( 'autocomplete' => array( 'server', 'servers' ) ) );
returns [{"autocomplete":["server","servers"]}] when appending format=json to the API URL. Instead of the above JSON string, the JavaScript client I'm working with needs {"autocomplete":["server","servers"]} in order to work correctly. In other words, I needed to get rid of [ and ].
Just out of curiosity, is a custom printer still the way to go?
In your API module, override getCustomPrinter():
public function getCustomPrinter() {
return new ApiFormatRaw(
$this->getMain(),
$this->getMain()->createPrinterByName( 'json' )
);
}
(the nested createPrinterByName() call is for fallback format in case of errors, you can change it to some other format)
Then, in your execute() method or wherever you need to return the value:
$this->getResult()->addValue( null, 'text', $data_you_want_to_return );
$this->getResult()->addValue( null, 'mime', 'application/json' );

How can I select specific JSON attributes for jstree?

I have implemented a jstree which uses the json_data plugin to retrieve json data with ajax from a server. The json attributed for one node look like:
{"data":"1","uri":"http://www.abc.com/1"}
My problem now is, how can I save these attributes in the jstree nodes? I know that there's a "data" option looking like this:
"data" : function (n) {
return { id : n.attr ? n.attr("id") : 0
};
I'm relativley new to jquery and jstree and I don't know how I can use the data option to
assign these attributed to the nodes. This is important because I have to get the JSON data from the tree after it was changed (using create, rename, remove, dnd operations) and therefore the JSON has to look like the one which was initially requested from the server through ajax.
Can somebody help me?
Have a nice day!
You create your json jsTree structure + data + all attributes on server side.
jsTree receives json and displays it. There might be some way how to tweak the data in javascript once you received it. Make it simple and do it on server side.
Below is bit of my server side script in ruby that creates json structure. Note that year, month etc are custom attributes.
hash_tmp = {
"data" => dir,
"attr" => { "group" => group,
"build_name" => build_name,
"year" => year_tmp,
"month" => month_tmp,
"daytime" => daytime,
"action" => action,
"rel" => type,
},
"state" => state,
"children" => ""
}