Now angularjs elvis is not required? - angularjs

I was watching a tutorial and learn about Elvis in angularjs. Then I create an object:
cabecaDeGelo{
name: 'jailson',
lastname: 'mendes',
address: {
street: null,
lol: 'lol'
}
}
And tried
Name: {{ cabecaDeGelo.name}} -> works fine
Street: {{ cabecaDeGelo.address.street }} -> works fine
WHAT???
{{ cabecaDeGelo.address.street }} generate a error 'cause doesn't exist! It is NULL! tutorial show a console error. I was thinking it's a version problem? Now I don't need anymore ELVIS?
like: {{ cabecaDeGelo.address?.street }}?
I was confused.
My configuration is#angular/cli: 1.0.4 / node: 6.10.3

Displaying a null or undefined value is not a problem (and has never been, neither in JavaScript, nor in an angular expression).
What is a problem and causes an exception is to display a property of a null or undefined reference.
For example:
const foo = {
bar: null
}
Displaying foo.bar if not a problem. What is a problem if to display, for example, foo.bar.baz, because you can't access a property (baz) of a null (or undefined) reference (foo.bar). That's where the null-safe navigation operator is needed:
{{ foo.bar?.baz }}: OK
{{ foo.bar.baz }}: exception

Related

Hugo data template telephone number gets rendered as a hash

I have a weird problem with Hugo and data templates.
I have link content in a json data template that i try to render inside an a tag like so:
data/foobar.json:
{ [ { link: 'tel:+123123', text: 'a' }, { link: 'mailto:mail#example.com', text: 'b' ] }
partial.html:
{{ range .Site.Data.foobar }}
{{ .text }}
{{ end }}
Which Produces:
a
b
For some reason the first anchor target renders out as a random hash, but the second one correctly. This seems to happen only when i start the link with tel:, and i can't understand why?
Probably syntax should be: {{ .link | safeURL }}
https://gohugo.io/functions/safehtml/
https://gohugo.io/functions/safehtmlattr/#readout
https://gohugo.io/functions/safeurl/
https://gohugo.io/functions/urlize/#readout
This is intentional as the link is not being sanitized.
See docs on Go and the way elements are rendered.
Off the cuff and not near my station - one of the above will point you in the right direction.
Check it and let me know.

Render last element of nested array of Object in Angular HTML template

I have an Object named comment, which has description property and editedDescription Array. Whenever user edits description, new description will be pushed into editedDescription array.This array is used so as to maintain history of edited descriptions.
Following is my comment Object :
export interface Comment {
userName: String,
userImage: String,
description: String,
upvote : Number,
downvote : Number,
createdDate: Date,
replies: [
{
userName: String,
userImage: String,
description: String,
upvote : Number,
downvote : Number,
createdDate: Date
}
],
editedDescription: [
{
Description: String,
editedDate: Date
}
]
}
In order to output last element of editedDescription array, I have tried :
{{ comment?.editedDescription[editedDescription?.length-1]?.Description}}
I am getting following error - 'Cannot read property '-1' of undefined '
I have made use of safe navigation operator to check if array exists but im getting cannot read -1 of undefined
this is my code where in part is failing
<div *ngIf="comment?.editedDescription?.length == 0 ; else edited_comment">
<p> {{ comment?.description }}</p>
</div>
<ng-template #edited_comment>
<p> {{ comment?.editedDescription[editedDescription?.length-1]?.Description}}</p>
</ng-template>
*ngIf conditions check if there is no data in editedDescription array, use description property else use last element of editedDescription array.
I think it needs to be the following, as at the moment you are not trying to access the array through comment where it sounds like it is stored.
{{ comment?.editedDescription[comment.editedDescription.length -1 ]?.Description}}
You still need to access comment when looking for the length. Put the safety operators back in when you are happy it is working. Below shows a simplified example of what you have tried.
const obj = { hello: [1, 2, 3] };
console.log(obj.hello[obj.hello.length - 1]); // last element, expected 3
// console.log(obj.hello[hello.length - 1]) // This is like what you have done.

VueJS Array update bug

I have a JSFiddle below to explain my problem but basically I have an array called tiles which has a title. When the instance is created() I add a field to this array called active
I then output this array in an <li> element and loop through it outputting the title and active objects. My problem is as you can see in the fiddle when I run v-on:click="tile.active = true" nothing happens to the active state written in the <li> element
but if I run v-on:click="tile.title = 'test'" it seems to update the active object and the title object.
Its strange behaviour I can't seem to work out why. Does anyone have any ideas?
https://jsfiddle.net/jgb34dqo/
Thanks
It's to do with Vue not knowing about your properties, change your array to this:
tiles: [
{
title: 'tile one',
active: false
},
{
title: 'tile two',
active: false
},
{
title: 'tile three',
active: false
}
]
This allows Vue to know about the active property and in turn it knows to monitor that variable.
It's worth looking at this link about Vue Reactivity as it helps with understanding how and when data will change automagically.
If you must add the properties after
take a look at $set. It allows you to add props to an object that then get watched by vue. See this fiddle, notice the change:
this.tiles.forEach(function(tile) {
// Tell vue to add and monitor an `active` prop against the tile object
this.$set(tile, 'active', false);
}.bind(this))

How to access objects in Jekyll array?

My Jekyll page code is as following (simplified):
_layouts/content.html:
---
layout: null
---
<pre>
{{ content }}
</pre>
any_page.md
---
layout: content
social:
- twitter :
url : "https://twitter.com"
user : "foo"
show : true
- instagram :
url : "https://instagram.com"
user : "bar"
show : false
---
My understanding of above in any_page.md is
social is an array of objects having items 0, 1; social[0] equals to * twitter. These keys can be variable.
each array item in above array is social[i]; an object having similar known keys (url, user, show)
Problem:
How to access page.social[i]["url"] & other two known keys?
How to access these known keys of an object residing in a variable-length array?
How to get the following outputs: twitter, https://twitter.com, foo, true
Code I have tried:
all social array: {{ page.social }} outputs (as expected)
{“twitter”=>
{ “url”=>”https://twitter.com”,
“user”=>”foo”,
“show”=>true
}
}
{“instagram”=>
{ “url”=>”https://instagram.com”,
“user”=>”bar”,
“show”=>false
}
}
social array's first object: {{ page.social[0] }} outputs (as expected)
{“twitter”=>
{ “url”=>”https://twitter.com”,
“user”=>”foo”,
“show”=>true
}
}
Failed attempts to access url of item 01 (all results to empty):
{{ page.social[0]["url"] }}
{{ page.social[0][url] }}
{{ page.social[0]."url" }}
{{ page.social[0].url }}
{{ page.social[0][0] }}
Addendum:
I have also tried the for loop; & it gives all the values on root level (twitter etc..), but no access to the object keys:
{% for item in page.social %}
item = {{ item }} # works
item[URL] = {{ item[url] }} # empty
item["URL"] = {{ item["url"] }} # empty
item."URL" = {{ item."url" }} # empty
item.URL = {{ item.url }} # empty
i = {{forloop.index }} # ok, but starts from 1 instead of 0
{% endfor %}
This will work:
twitter key: {{page.social[0]|first|first}}
<h2>data</h2>
url: {{page.social[0]['twitter'].url}}
user: {{page.social[0]['twitter'].user}}
show: {{page.social[0]['twitter'].show}}
Another approach
social:
twitter :
url : "https://twitter.com"
user : "foo"
show : true
instagram :
url : "https://instagram.com"
user : "bar"
show : false
Then you can access it with:
{% for item in page.social%}
key: {{item[0]}}<br>
{% endfor %}
<hr>
<h2>data</h2>
url: {{page.social['twitter'].url}}
user: {{page.social['twitter'].user}}
show: {{page.social['twitter'].show}}
I have accepted marcanuy's answer, here I am just documenting what I used based on his answer;
{% for item in page.social %} # OUTPUT for 1st item
{{ item[0] }} # twitter:
{{ item[1].url }} # https://twitter.com
{{ item[1].user }} # foo
{{ item[1].show }} # true
{% endfor %}
Also, the declaration in front matter is bit changed. The one which works with above code is:
social:
twitter :
url : "https://twitter.com"
user : "foo"
show : true
instagram :
url : "https://instagram.com"
user : "bar"
show : false
Note the missing - dashes. Although both ways are correct, I need to read more to how to access both.
As mentioned at http://yaml.org/spec/1.2/spec.html, indentations & - matter. Each item having more spaces than earlier makes itself child of earlier.

How to display value of object sent by node

I have question i try to put value from nodejs by init() in angularjs, later i put to $scope.product and when i try display i have problem with:
node:
return res.render('product/product', { title: 'Express', product: products });
angular:
<body ng-controller="productsController" ng-init="productView('<%= product %>')">
<% include ../share/header.ejs %>
{{ product.title }}
{{ product.price }}
</body>
controller:
$scope.productView = function (product) {
$scope.product = JSON.parse(product);
console.log(product);
};
Error: [$parse:syntax] Syntax Error: Token 'bf' is unexpected, expecting [)] at column 55 of the expression [productView('{ _id: 5950c8902a76e81b5cc56a6f, title: 'bf', price: 7, __v: 0 }')] starting at [bf', price: 7, __v: 0 }')].
product: products - it's possible you are passing down an array of objects instead of an individual one. If that's the case, either change the res.render call on the server to pass only 1 product, or change the client-side code to expect an array and use something like ngRepeat to iterate over them.
you dont need productView function, try simply
<body ng-controller="productsController" ng-init="product='<%= product %>'">
{{ product.title }}
{{ product.price }}

Resources