Vue for loop for objects not working - javascript

I am trying to create a top menu with dropdown buttons when iterating over an object that looks like this:
links: {
store: 'store',
language: [{'target': '/english'},{'target': '/norwegian'}],
login: 'user/login'
}
I have tried to achieve that by making a loop that looks like this:
<div v-for="(value, key) in links" :key="key" class="control">
<div v-if='Array.isArray(value)'>
<dropdown-menu :menu="value"></dropdown-menu>
</div>
<div v-else>
<a :href="value">
{{ key }}
</a>
</div>
</div>
But, I get errors:
Property or method "value" is not defined on the instance but
referenced during render. Make sure to declare reactive data
properties in the data option.
Even if I declare the value and key with initial values of null, it is not rendering anything:
data() {
return {
data: null,
value: null,
key: null,
};
},
This is the dropdown menu component:
<template>
<div class="dropdown is-active">
<div class="dropdown-trigger">
<button class="button" aria-haspopup="true" aria-controls="dropdown-menu">
<span>Dropdown button</span>
<span class="icon is-small">
<i class="fa fa-angle-down" aria-hidden="true"></i>
</span>
</button>
</div>
<div class="dropdown-menu" id="dropdown-menu" role="menu">
<div class="dropdown-content">
<a href="#" class="dropdown-item">
Dropdown item
</a>
<a class="dropdown-item">
Other dropdown item
</a>
<a href="#" class="dropdown-item is-active">
Active dropdown item
</a>
<a href="#" class="dropdown-item">
Other dropdown item
</a>
<hr class="dropdown-divider">
<a href="#" class="dropdown-item">
With a divider
</a>
</div>
</div>
</div>
</template>
<script>
export default {
name: 'dropdown-menu',
props: ['menu'],
data() {
return {};
},
};
</script>
But, the dropdown menu is not even shown in the vue dev tools when I go to the top-bar component.
Update
For some reason if I removed the divs, and changed the template to this:
<dropdown-menu v-if='Array.isArray(value)' :menu="link"></dropdown-menu>
<a :href="value" v-else>
{{ key }}
</a>
If somebody could explain it, that would be great.

Related

Bulma burger isn't shown

I have a problem with the Bulma framework. I have a small navbar for desktop and want to add a navbar burger. But it doesn't work. I tried the js script created by Bulma as an example and one from a yt video. Both didn't work. Can somebody Please help me? Down will find the html part and the js script:
js/index.js
document.addEventListener('DOMContentLoaded', () => {
// Get all "navbar-burger" elements
const $navbarBurgers = Array.prototype.slice.call(document.querySelectorAll('.navbar-burger'), 0);
// Add a click event on each of them
$navbarBurgers.forEach( el => {
el.addEventListener('click', () => {
// Get the target from the "data-target" attribute
const target = el.dataset.target;
const $target = document.getElementById(target);
// Toggle the "is-active" class on both the "navbar-burger" and the "navbar-menu"
el.classList.toggle('is-active');
$target.classList.toggle('is-active');
});
});
});
index.html
<script src="js/index.js"></script>
<nav class="navbar" role="navigation" aria-label="main navigation">
<div class="navbar-brand">
<a class="navbar-item" href="index.html">
<h1 class="title">10.8</h1>
</a>
<a role="button" class="navbar-burger" data-target="navMenu" aria-label="menu" aria-expanded="false">
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
</a>
<div class="navbar-menu" id="navMenu">
<div class="navbar-menu">
<div class="navbar-start">
<a class="navbar-item">
Home
</a>
<div class="navbar-item has-dropdown is-hoverable">
<a class="navbar-link">
More
</a>
<div class="navbar-dropdown">
<a class="navbar-item">
About
</a>
<a class="navbar-item">
Jobs
</a>
<a class="navbar-item">
Contact
</a>
<hr class="navbar-divider">
<a class="navbar-item">
Report an issue
</a>
</div>
</div>
</div>
<div class="navbar-end">
<!-- navbar items -->
</div>
</div>
</div>
</nav>
Well if watched a small video produced from Bulma, tried the code from theire website and watched another video. I also tried to write my own script but it also does'nt work.
I hope sb can help me to fix it cause this must be successfully really quick.
You have a div that doesn't close in the right place.
There is a div with duplicate className.
Properly closing and removing that div everything works as expected.
// Get all "navbar-burger" elements
const $navbarBurgers = Array.prototype.slice.call(document.querySelectorAll('.navbar-burger'), 0);
// Add a click event on each of them
$navbarBurgers.forEach(el => {
el.addEventListener('click', () => {
// Get the target from the "data-target" attribute
const target = el.dataset.target;
const $target = document.getElementById(target);
// Toggle the "is-active" class on both the "navbar-burger" and the "navbar-menu"
el.classList.toggle('is-active');
$target.classList.toggle('is-active');
});
});
<link href="https://cdnjs.cloudflare.com/ajax/libs/bulma/0.9.4/css/bulma.min.css" rel="stylesheet"/>
<body>
<nav class="navbar" role="navigation" aria-label="main navigation">
<div class="navbar-brand">
<a class="navbar-item" href="index.html">
<h1 class="title">10.8</h1>
</a>
<a role="button" class="navbar-burger" data-target="navMenu" aria-label="menu" aria-expanded="false">
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
<span aria-hidden="true"></span>
</a>
</div>
<div class="navbar-menu" id="navMenu">
<div class="navbar-start">
<a class="navbar-item">
Home
</a>
<div class="navbar-item has-dropdown is-hoverable">
<a class="navbar-link">
More
</a>
<div class="navbar-dropdown">
<a class="navbar-item">
About
</a>
<a class="navbar-item">
Jobs
</a>
<a class="navbar-item">
Contact
</a>
<hr class="navbar-divider">
<a class="navbar-item">
Report an issue
</a>
</div>
</div>
</div>
<div class="navbar-end">
<!-- navbar items -->
</div>
</div>
</nav>
</body>

Bootstrap Dropdown Button not displaying V-For Elements

I have the following Vue.js (3) component, which uses Bootstrap (5):
<template>
<div class="dropdown">
<button class="btn btn-secondary dropdown-toggle btn-link text-decoration-none text-dark" type="button" id="languageDropdown" data-bs-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
{{ languages[$i18n.locale] }}
</button>
<div class="dropdown-menu" aria-labelledby="languageDropdown" v-for="(value, key) in languages" v-bind:key="key">
<a class="dropdown-item" href="#" #click="changeLanguage(key)">{{ value }}</a>
</div>
<li v-for="(value, key) in languages" v-bind:key="key">
{{ key }}: {{ value }}
</li>
</div>
</template>
<script>
export default {
name: "LanguageSwitcher",
data() {
return {
languages: {
'en': 'English',
'de': 'Deutsch',
}
};
},
methods: {
changeLanguage: function(lang){
this.$i18n.locale = lang;
}
}
};
</script>
Without the v-for everything works fine. But as soon, as I add it, only the first element of the object languages gets rendered.
As you can see, the list is rendered correctly, with both languages.
Only in the dropdown, "Deutsch" (German) is not rendered.
Is this a bug with Bootstrap/Vue or am I missing something?
im able to solve this by moving the v-for syntax to a template
so instead of this:
<div class="dropdown-menu" aria-labelledby="languageDropdown" v-for="(value, key) in languages" v-bind:key="key">
<a class="dropdown-item" href="#" #click="changeLanguage(key)">{{ value }}</a>
</div>
do this:
<div class="dropdown-menu" aria-labelledby="languageDropdown">
<template v-for="(value, key) in languages" v-bind:key="key">
<a class="dropdown-item" href="#" #click="changeLanguage(key)">{{ value }}</a>
</template>
</div>

Links on my website are not working

I have a bootstrap website. At first, my links were concatenating (e.g. if I were to click on the home index page three times it would show instastatus.live/index.html/index.html/index.html) every time I clicked a link.
The issue has been solved, but now the link won't go through. For example, if I click one of the nav bar items such as "Services", the URL shows the correct address: instastatus.live/services/index.html. However, it won't go to the page until I click on the URL bar and hit enter (only then will it take me to the appropriate page). Otherwise, it does nothing.
<nav class="cb-navbar">
<div class="cb-container">
<div class="cb-navbar-inner">
<div class="cb-navbar-left">
<a href="index.html" class="cb-navbar-back">
<i class="cb-icon -long-arrow-left"></i>
</a>
</div>
<div class="cb-navbar-right">
<div class="cb-navbar-nav">
<a href="/services/index.html" id="navbar-services" class="cb-navbar-nav-item">
<span class="cb-navbar-nav-item-icon">
<i class="cb-icon -cog"></i>
</span>
<span class="cb-navbar-nav-item-text">Services</span>
</a>
<a href="/projects/index.html" id="navbar-projects" class="cb-navbar-nav-item">
<span class="cb-navbar-nav-item-icon">
<i class="cb-icon -bars"></i>
</span>
<span class="cb-navbar-nav-item-text">Projects</span>
</a>
<a href="/contacts/index.html" onclick="yaCounter.reachGoal('contacts')" id="navbar-contacts" class="cb-navbar-nav-item">
<span class="cb-navbar-nav-item-icon">
<i class="cb-icon -contacts"></i>
</span>
<span class="cb-navbar-nav-item-text">Contacts</span>
</a>
</div>
</div>
</div>
</div>
</nav>

Angular 2 Transclusion with Template Outlet

I have a Component with view like below:
<div class="dropdown user-select">
<div class="gray-input dropdown-toggle" type="button" id="assigned_to" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
<ng-content select="[selected-item-tmpl]"></ng-content>
<span class="caret"></span>
</div>
<ul class="dropdown-menu" aria-labelledby="assigned_to">
<li *ngFor="let item of items"
(click)="itemClick$.next(item)">
<ng-content select="[list-item-tmpl]"></ng-content>
</li>
</ul>
</div>
According to this and this, I now know that Transclusion with ngFor will not work.
But according to this, if I change my component to following:
<div class="dropdown user-select">
<div class="gray-input dropdown-toggle" type="button" id="assigned_to" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
<ng-content select="[selected-item-tmpl]"></ng-content>
<span class="caret"></span>
</div>
<ul class="dropdown-menu" aria-labelledby="assigned_to">
<li *ngFor="let item of items"
(click)="itemClick$.next(item)">
<template [ngTemplateOutlet]="template"
[ngOutletContext]="{item: item}">
</template>
</li>
</ul>
</div>
For brevity the Component.ts after change:
#ContentChild(TemplateRef) template: TemplateRef<any>;
and use like following:
<ds-combobox [items]="attendeeService.users"
(itemClicked)="applySelectedUser($event)">
<div selected-item-tmpl>
--> <img *ngIf="newTask.assignedTo.photo" [src]="newTask.assignedTo.photo">{{newTask.assignedTo.name}}
<div *ngIf="!newTask.assignedTo.photo && newTask.assignedTo.initials" class="pull-left photo-avatar">
<div>{{newTask.assignedTo.initials}}</div>
</div>
</div>
<div list-item-tmpl>
<template let-item="item"><b>{{item.name}}</b></template>
</div>
</ds-combobox>
Then I do not get any errors and it seems to run but the template for the ngTemplateOutlet seems to take the template from the first slot and ends up being <img src="null">. If I remove the first slot and just leave <template let-item="item"><b>{{item.name}}</b></template> then it seems to work fine. So basically, how do I combine using Transclusion with Template Outlet in the same component?
NOTE:
After thinking for a while, I just reversed the <template> position with <ng-content> and it seems to work now as expected. But the question still remains why though?

add CSS element using an angular directive

Im using angular and ng-repeat to populate a list of studies. This list is dynamic so you can toggle into child elements of each element. So basically I have a accordion style toggle list that can go three levels deep on each list item. I have a jQuery issue that I think should be solved with some angular directive or something. Basically I have an arrow (glyphicon) that should switch to up or down depending on if your looking at a child or a parent element in this list. I have this working with pure jQuery just adding and removing a css class from each list item. However, it only works on the first item in the list because ng-repeat creates multiple id’s but jQuery will only work on the first element with that id tag.
This is the HTML from the page.
<!-- User Studies List -->
<div ng-controller="StudiesController" id="before">
<h3 class="center"> User Studies </h3>
<div ng-repeat="study in studies" arrow>
<div class="panel-group" style="margin-bottom:0">
<div class="panel panel-default">
<div class="panel-heading" data-toggle="collapse" href="#collapse{{$index}}">
<h3 class="panel-title">{{ study.study }} <span class="glyphicon glyphicon-menu-down pull-right"></span></h3>
<p></p>
</div>
<div id="collapse{{$index}}" class="panel-collapse collapse">
<ul class="list-group">
<li class="list-group-item" data-toggle="collapse" href="#collapse{{study.id}}" style="margin-left:1%" id="sampleID{{$index}}">
<i>Sample: </i>{{ study.sample }}
<span id="glyph-switch" class="glyphicon glyphicon-menu-down pull-right"></span>
<span id="glyph-up" class="glyphicon glyphicon-menu-up pull-right"></span>
</li>
<div id="collapse{{study.id}}" class="panel-collapse collapse">
<ul class="list-group">
<li class="list-group-item" style="margin-left:3%"><i>Fastq: </i>{{ study.fastq }}
<div class="dropdown center pull-right">
<button class="btn-xs btn-default hvr-shadow" id="dLabel" type="button" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">
Action <span class="caret"></span>
</button>
<ul class="dropdown-menu" aria-labelledby="dLabel">
<li id="list-item" data-toggle="modal" data-target="#more-metadata-modal" ng-click="showMore(study)">More Data</li>
<li id="list-item" data-toggle="modal" data-target="#edit-metadata-modal" ng-click="showMore(study)">Edit</li>
<li id="list-item" data-toggle="modal" data-target="#delete-metadata-modal" ng-click="showMore(study)">Delete</li>
</ul>
</div>
</li>
</ul>
</div>
</ul>
</div>
</div>
</div>
</div>
</div>
This is the Javascript
var count = 1;
$(document).on("click", "li[id*='sampleID']", function() {
console.log("clicked");
if(count > 0) {
$('#glyph-switch').css('visibility','hidden');
$('#glyph-up').css('visibility', 'visible');
count -= 1;
console.log("count", count);
} else {
$('#glyph-switch').css('visibility','visible');
$('#glyph-up').css('visibility', 'hidden');
count += 1;
console.log("count",count);
}
});
I would just use angular code (no jQuery at all).
Since you already have an object of studies, just handle an onClick="showGlyph($index)" passing the index and then in the code just set the a state for the up/down arrow $scope.GlyphUp = !$scope.GlyphUp.
In the template file have the up/down arrow object bind ng-show="GlyphUp"

Categories

Resources