My code is behaving strangely. Indeed, I created my data in a JSON object:
injectJson = {
"title": "Questions for a champion",
"rules": [
{
"idChrono": "chrono-minute",
"text": "Top is gone!",
"tag": [
{
"id": "chronometer",
"text": "countDown"
}
]
}
]
}
Here is my HTML code:
<div id="rules">
<h3>The game's rules!</h3>
</div>
<div id="begin">
Begin
</div>
And here is the Javascript code with which I inject the HTML code:
selectLinkBegin = document.getElementById("begin");
selectLinkBegin.firstElementChild.addEventListener("click", function(injectJson) {
// Injection code
selectRules = document.getElementById("rules");;
selectRules.firstElementChild.innerText = injectJson.rules[0].texte;
});
In my computer,the JSON object and the JavaScript code are in the same .js file. I load my script at the end of the body tag.
When I open my .html code in the browser, the console displays:
Uncaught TypeError: Cannot read property '0' of undefined
at HTMLAnchorElement.
But when I copy the Javascript code into the console, I get the expected result: h3's text content is updated.
Demo:
injectJson = {
"title": "Questions for a champion",
"rules": [{
"idChrono": "chrono-minute",
"text": "Top is gone!",
"tag": [{
"id": "chronometer",
"text": "countDown"
}
]
}]
}
selectLinkBegin = document.getElementById("begin");
selectLinkBegin.firstElementChild.addEventListener("click", function(injectJson) {
// Injection code
selectRules = document.getElementById("rules");;
selectRules.firstElementChild.innerText = injectJson.rules[0].texte;
});
<div id="rules">
<h3>The game's rules!</h3>
</div>
<div id="begin">
Begin
</div>
Can you explain to me what is going on? How to remedy this? I have already emptied my cache but it's still the same.
Your problem is that the variable injectJSON is being hoisted by the param in your click event handler callback function, so it will be undefined that's why you got the error:
Uncaught TypeError: Cannot read property '0' of undefined at HTMLAnchorElement.
In other words the callback param has the same name as your injectJson variable, so that means your original injectJson variable will be undefined, as it was overridden by this param.
You can check the Variable Hoisting section here for further reading about this.
So what you need to do is to remove the callback param:
selectLinkBegin.firstElementChild.addEventListener("click", function() {
// Injection code
selectRules = document.getElementById("rules");;
selectRules.firstElementChild.innerText = injectJson.rules[0].text;
});
Note:
Make sure to access the right text element instead of texte in
injectJson.rules[0].texte.
Make sure to declare your variables with var keyword and avoid using an existing variable name, to avoid such problems.
Demo:
var injectJson = {
"title": "Questions for a champion",
"rules": [{
"idChrono": "chrono-minute",
"text": "Top is gone!",
"tag": [{
"id": "chronometer",
"text": "countDown"
}
]
}]
}
selectLinkBegin = document.getElementById("begin");
selectLinkBegin.firstElementChild.addEventListener("click", function() {
// Injection code
selectRules = document.getElementById("rules");;
selectRules.firstElementChild.innerText = injectJson.rules[0].text;
});
<div id="rules">
<h3>The game's rules!</h3>
</div>
<div id="begin">
Begin
</div>
Related
The following example gives me a blank screen (jsfiddle here). Even the parts which have nothing to do with the loop are not being rendered.
HTML:
<div id="app">
<button #click="objectFromApi">
run objectFromApi function
</button>
<div
v-for="obj in myObject[0].results"
:key="obj.id"
>
<p>
{{ obj.message }}
</p>
</div>
</div>
JavaScript:
new Vue({
el: "#app",
data: {
myObject: []
},
methods: {
objectFromApi: function(){
this.myObject.push(
{
"count": 5,
"results": [
{
"id": 1,
"message": "object 1"
},
{
"id": 2,
"message": "object 2"
}
]
}
)
}
},
//created() {
// this.objectFromApi()
//}
})
Nevertheless it does work if:
1.) Either using objectFromApi function directly in the created life cycle hook (what I don't want!)
created() {
this.objectFromApi()
}
2.) Or (without the use of created life cycle hook) if I go directly into the nested results array and spread the objects out like this (what I also don't want!)
this.myObject.push(
...{
"count": 5,
"next": "http://127.0.0.1:8000/api/someurl/?page=2",
"previous": null,
"results": [
{
"id": 1,
"message": "object 1"
},
{
"id": 2,
"message": "object 2"
}
]
}.results
)
When using option 2.) of course the v-for loop has to look different:
v-for="obj in myObject" instead of v-for="obj in myObject[0].results"
What is wrong with my initial example?
When the component is first rendering the array myObject will be empty.
During rendering it attempts this:
<div
v-for="obj in myObject[0].results"
:key="obj.id"
>
The value of myObject[0] will be undefined. Attempting to access the results property of undefined will result in an error. This error will cause rendering to fail. Nothing will be shown, even the parts that didn't fail.
There are various ways to fix this problem. You could prepopulate the data with suitable empty properties:
data: {
myObject: [
{
results: []
}
]
}
Alternatively, as you've noted, you could change the loop to use v-for="obj in myObject", changing objectFromApi accordingly to only store the results array in myObject. Even if you don't want that exact change some similar change is probably a good idea because the [0] part strongly suggests you've got a problem with your data model. The key thing here is that it avoids trying to access nested objects that don't exist. The use of the spread operator in your second example is largely irrelevant.
Or you could skip the loop in the template:
<template v-if="myObject[0]">
<div
v-for="obj in myObject[0].results"
:key="obj.id"
>
...
</div>
</template>
I am trying to access the value of a variable present inside a script tag. But I am not able to retrieve the value. I tried in few ways but I don't get the expected result.
I need to get the values and parse and do some operations over it but I am blocked from morning can u please some one help me it's ruining my time.
var scriptTag = document.getElementsById('test');
console.log(scriptTag.window["ytInitialData"]); //shows undefined
console.log(scriptTag.getAttribite(window["ytInitialData"])); // shows null
<script id="test">
window["ytInitialData"] = {
"responseContext": {
"serviceTrackingParams": [{
"service": "GFEEDBACK"
}]
}
};
window["ytInitialPlayerResponse"] = {
"responseContext": {
"serviceTrackingParams": [{
"service": "GFEEDBACK"
}]
}
};
if (window.ytcsi) {
window.ytcsi.tick("pdr", null, '');
}
</script>
The window object is global and can be accessed from any script on your page, so set the window property like this:
window.ytInitialData = {
"responseContext": {
"serviceTrackingParams": [{
"service": "GFEEDBACK"
}]
}
}
"ytInitialData" is a string literal so you can use dot notation instead of brackets.
Then access it again anywhere later in your script the same way:
console.log(window.ytInitialData)
window.ytInitialData = {
"responseContext": {
"serviceTrackingParams": [{
"service": "GFEEDBACK"
}]
}
}
console.log(window.ytInitialData)
I have a nav menu that is rendered using a navigation.ts json file for the menu items. When it gets to the navitem component it uses a ngIf to check if the item from the navigation file has a "function" key and if it does, the desired behavior is for it to use the string value from item.function in the object to fill the value for the (click) event.
In reality, the console throws an error saying "_co.item.function is not a function"
HTML
<span class="nav-link" *ngIf="item.function" (click)="item.function()" matRipple>
<mat-icon class="nav-link-icon" *ngIf="item.icon">{{item.icon}}</mat-icon>
<span class="nav-link-title" [translate]="item.translate">{{item.title}}</span>
<span class="nav-link-badge" *ngIf="item.badge" [translate]="item.badge.translate"
[ngStyle]="{'background-color': item.badge.bg,'color': item.badge.fg}">
{{item.badge.title}}
</span>
</span>
Navigation.ts
[{
"id": "accounting",
"title": "Accounting",
"type": "collapse",
"children": [
{
"id" : "salesmenSalesLocation",
"title": "Salesmen Sales Location",
"type": "item",
"function": "handleSelect(ReportTypes.SalesmenSalesLocations)"
},
{
"id": "laggingLedgerEntries",
"title": "Lagging Ledger Entries",
"type": "item",
"function": "handleSelect(ReportTypes.LaggingLedgerEntries)"
}
]}]
I have also tried it as (click)="item.function" with no success.
I'm assuming you can change the data source here, because otherwise I don't see any good solution.
A string is not a function, and while you can turn it into one with eval that is a bad idea. What you should really do instead is just pass in a value that tells the function what to use.
Change your data to something like this:
{
"id" : "salesmenSalesLocation",
"title": "Salesmen Sales Location",
"type": "item",
"reportTypeSource": "SalesmenSalesLocations"
},
{
"id": "laggingLedgerEntries",
"title": "Lagging Ledger Entries",
"type": "item",
"reportTypeSource": "LaggingLedgerEntries"
}
Then pass that value to your function and use that to tell it where to look:
handleSelect (reportTypeSource: string) {
const reportType = ReportTypes[reportTypeSource]
// continue as before
}
And call it in your HTML like this:
(click)="handleSelect(item.reportTypeSource)"
Problem lies here:
"function": "handleSelect(ReportTypes.LaggingLedgerEntries)"
And here:
(click)="item.function()"
You cannot simply pass a string and expect the component to execute a function and also know exactly what to do. Here you need to pass the actual function.
Your setup looks over-config'd. I would tear the config down and put the logic into the component itself. Don't be afraid to have more template as well, if anything it makes things more legible (as opposed to the config)
Does that function exist in the component or just the model? If it is just on the model it won't work. (click) is looking for a method on the component. It is, ostensibly just a string in this instance.
Here is my Json data
"data": {
"address": {
"postalCode": "112629",
"state": "DL",
"city": "new city",
"streetAddress": "my street"
},
"specialities": [
{
"_id": "577692f7",
"name": "Football",
"description": "game",
"__v": 0
}
]
}
$scope.test = data;
i am fetching data in html by
ng-repeat="mytest in test" than
mytest.address.city // this is working fine
mytest.specialities.name // not printing anything
i am facing the problem in accessing the specialities name i think that is because of specialities is a array but don't know how to get it.
You defined a specialities object with only one array inside
try
mytest.specialities[0].name
Update:
Also you may want to make sure that the array has at least one element, otherwise you mayget a TypeError: Cannot read property 'name' of undefined.
So the code sould look like this:
mytest.specialities.length > 0 ? mytest.specialities[0].name : '(some default value)';
Assuming there will be many specialities you should use ng-repeat to display them all.
<p ng-repeat="s in mytest.specialities"> {{s.name}} / {{s._id}} / {{s.description}} </p>
Yes mytest.specialities is array. JSON has two possible options [ ] - array, { } - object. In this situation we have array of objects - [ { /* object data */ } ] so to get object parameter first go to array element like this ( example getting first element on index 0 ):
mytest.specialities[0].name
second element:
mytest.specialities[1].name
example each:
<div ng-repeat="special in mytest.specialities">
<span>{{special.name}}</span>
</div>
of course before that set mytest to scope like:
$scope.mytest=mytest;//mytest is your data structure
I am trying to generate a JSON document from a form. The output I want would look something like this:
{
"name": "joe-pc",
"device_type": "server",
"os": "windows",
"info": [
{
"net_info": [
{
"ip": "192.168.0.5",
"name": "eth0"
},
{
"ip": "192.168.0.28",
"name": "eth1"
}
]
},
{
"OS_info": [
{
"name": "windows"
},
{
"build": "123.1.3"
}
]
},
{
"whatever_info": [
{}
]
}
]
}
What I'm getting is:
{"info":[{}]}
Code Snips:
$('#top_three_next').click(function (e) {
var json_obj = new Object();
json_obj.name = $('#name').val(); //manditory
json_obj.device_type = $('#device_type').val(); //manditory
json_obj.os = $('#os').val(); //not a manditory field
// is this not available outside the function?
// even if I declare json_obj as a global var?
});
Full code:
http://jsfiddle.net/jdell64/Tu9bB/ (start at line 93 in the js pane).
First of all your code on jsfiddle looks a bit messy :)
I see
var json_obj = new Object();
declaration on line 95. This Line is not needed at all. Because you already defined empty json_obj at the beginning of your JS. And this declaration overheads global variable & uses local variable from callback scope & all data filled in it is missing after callback ends. If you remove that line you'll get the following structure at the end.
{"name":"1","device_type":"2","os":"3","info":[{}]}
EDITED:
Also lines 191-192 is totally unclear for me:
infoList.push(infoDocs);
json_obj.info = infoList;
Both infoDocs & infoList variables is not defined in event handler function, but they also not defined globally!