I get a list from my backend:
[
{
'name': 'nameA',
'codename': 'codenameA'
},
{
'name': 'nameB',
'codename': 'codenameB'
},
{
'name': 'nameC',
'codename': 'codenameC'
}
My goal is to display a list of owner.name with a url like http://myurl/owner/edit/${{ owner.codename }} using VueJS.
Currently my code is :
<template>
<div class="container my-3">
<div class="row">
<div class="col-8">
<ul v-for="owner in this.databaseOwners" :key="owner.name" class="list-group">
<li class="list-group-item">
{{ owner.name }}
</li>
</ul>
</div>
</div>
</div>
</template>
But it doesn't work, how can I use dynamic URL in my case? I'm really new to frontend so I'm sorry if my question seems really trivial.
Try this:
Make a new method under methods property of your Vue component:
methods: {
url(codename) {
return `/admin/owner/${codename}`;
}
}
And use it like this:
<a :href="url(owner.codename)">...</a>
Pay attention to the colon symbol:
:href
It means that it will try and bind the href attribute to some variable/method/computed property that is coming from the Vue component
This works : <a :href="'/admin/owner/' + owner.codename">{{ owner.name }}</a>
this may work
<a :href="'localhost:8080/admin/owner/'+owner.codename " target="_blank" rel="noreferrer noopener">{{ owner.name }}</a>
Related
I have an input that I'm using in relation two an unordered list with two list items, which is in place, but I"m trying to figure out how I can change the input name/id with the click of one of the list items.
The items are not links or buttons, so I just want to be able to click the item text and if 'Public' is clicked, the input name would become public, if 'Internal' is clicked I would want the input name to be internal
I'm using Vue which may have some better options, but basically I just want to send the name of the input later on in an ajax call and I only want the name to be determined by the click of a list item potentially with a default.
What is the best way to achieve this with Vue being used?
<div class="row notesInput">
<div class="col-lg-12">
<div class="tabs">
<ul style="border-bottom:none !important; text-decoration:none">
<li>Public</li>
<li>Internal</li>
</ul>
</div>
<div>
<input type="text" name="public">
</div>
</div>
</div>
First step: use component data to your advantage
You can simply store the desired input name attribute in the component data, e.g. inputName. Then, use v-on to bind a click event listener to your elements, so that whenever they are clicked, you invoke a method that updates the inputData property of your component.
new Vue({
el: '#app',
data: {
inputName: '',
},
methods: {
setInputName(str) {
this.inputName = str;
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div class="row notesInput">
<div class="col-lg-12">
<div class="tabs">
<ul style="border-bottom:none !important; text-decoration:none">
<li v-on:click="setInputName('public')">Public</li>
<li v-on:click="setInputName('internal')">Internal</li>
</ul>
</div>
<div>
<input type="text" v-bind:name="inputName">
<br />
Input name attribute is: {{ inputName }}
</div>
</div>
</div>
</div>
Better: Use v-for to generate list items dynamically
If you don't want the manually provide the argument to the method, there's an easier way: you simply create a list of allowed names in the component data, too, and use v-for to generate the list dynamically:
new Vue({
el: '#app',
data: {
inputName: '',
allowedNames: ['Public', 'Internal']
},
methods: {
setInputName(str) {
this.inputName = str.toLowerCase();
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div class="row notesInput">
<div class="col-lg-12">
<div class="tabs">
<ul style="border-bottom:none !important; text-decoration:none">
<li
v-for="(allowedName, i) in allowedNames"
v-bind:key="i"
v-on:click="setInputName(allowedName)">
{{ allowedName }}
</li>
</ul>
</div>
<div>
<input type="text" v-bind:name="inputName">
<br />
Input name attribute is: {{ inputName }}
</div>
</div>
</div>
</div>
Even better: if there is no one-to-one correspondance between list item text and the desired name attribute
This can be useful in the case when, for example, you want the text to read Public but the name attribute to be another value. Instead of an array of strings, you can use an array of objects:
new Vue({
el: '#app',
data: {
inputName: '',
allowedNames: [{
label: 'Public (or any other arbitrary text you like)',
name: 'public'
}, {
label: 'Internal (or any other arbitrary text you like)',
name: 'internal',
}]
},
methods: {
setInputName(str) {
this.inputName = str;
}
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="app">
<div class="row notesInput">
<div class="col-lg-12">
<div class="tabs">
<ul style="border-bottom:none !important; text-decoration:none">
<li
v-for="(allowedName, i) in allowedNames"
v-bind:key="i"
v-on:click="setInputName(allowedName.name)">
{{ allowedName.label }}
</li>
</ul>
</div>
<div>
<input type="text" v-bind:name="inputName">
<br />
Input name attribute is: {{ inputName }}
</div>
</div>
</div>
</div>
I have an array of items, which looks like this:
nav: any = [
{
name: 'Homepage',
url: 'homepage'
internal: false
},
{
name: 'Section 1',
hash: 'section-1'
internal: true
},
];
Now I need to ouput a list of a-elements. These should either contain a routerLink if internal is false – or they should become an internal anchor. I've tried:
<a class="link"
*ngFor="for item of nav"
[href]="item.internal ? '#' + item.hash : null"
[routerLink]="item.internal ? null : item.url">
{{ item.title }}
</a>
This renders homepage correctly, but Section 1 comes out wrongly:
<a class="link" href="/homepage">Homepage</a>
<a class="link" href="/">Section 1</a>
This is what I actually want:
<a class="link" href="/homepage">Homepage</a>
<a class="link" href="#section-1">Section 1</a>
How to achieve this correctly?
Try this...
<a class="link" *ngFor="for item of nav" [routerLink]="item.internal ? '#' + item.hash : item.url">
{{ item.title }}
</a>
The routerLink replaces by href after render.
why not conditionally, use one or the other?
<ng-container *ngIf="internal">
show appropriate link
</ng-container>
<ng-container *ngIf="!internal">
show appropriate link
</ng-container>
I hope the title isn't too confusing.
I have an array in my angular.js file:
var app = angular.module('resume', []);
app.controller('resumeCtrl', function($scope, $document) {
$scope.projects = [
{
title: 'TRU Colors Brewing Co.',
image: 'images/tcb_screenshot.png',
url: 'https://www.trucolors.co',
category: ['development', 'design']
},
{
title: 'JOMO',
image: 'images/jomo_screenshot.png',
url: 'https://jeffberlin.github.io/JOMO_website/index.html',
category: 'development'
}
];
And in my HTML file I have:
<div class="row portfolio-preview">
<div class="col-lg-4 text-center" ng-repeat="x in projects">
<div class="projects tab-content active">
<figure class="tab-pane">
<a ng-href="{{x.url}}" target="_blank">
<img class="img-fluid screenshot" ng-src="{{x.image}}">
</a>
</figure>
<div class="description">
<a href="" target="_blank">
<h5>{{x.title}}</h5>
</a>
</div>
</div>
</div>
Now my issue is, I get the correct number of boxes to show with the titles, but nothing else displays/shows from the array. For reference, this section will have 3 options in the nav area and filter them out (by the category), assuming that's the best to do it. Can anyone see something I might be doing wrong?
The HTML code shown is the only way I've been able to at least get the titles to show up by using x in projects and the x.image, x.title, etc.
P.S.- I'm very new to Angular, but appreciate you all taking the time to help!
You need to provide a relative path to your images folder. The path needs to be relative to where your html file is so the browser knows where to look properly.
Add ./ in front of your image url.
$scope.projects = [
{
title: 'TRU Colors Brewing Co.',
image: './images/tcb_screenshot.png',
url: 'https://www.trucolors.co',
category: ['development', 'design']
},
{
title: 'JOMO',
image: './images/jomo_screenshot.png',
url: 'https://jeffberlin.github.io/JOMO_website/index.html',
category: 'development'
}
];
and as pointed out in the comments your css might be causing the image to be hidden or not have a width or height. So when debugging don't forget to check the css.
I have an array of the following class:
export class Ref {
constructor(
private id: number,
private image: string,
private title: string,
private descript: string,
private url: string,
private urlType: string,
) { }
}
and in my html I call it like this:
<div class="row">
<div class="col-sm-3" *ngFor="let r of ref">
<a [href]="r.url" [target]="r.urlType" class="reforms-1">
<img class="refimg" [src]="r.image" alt="">
<span class="reftitle"><h4>{{r.title}}</h4></span>
<span class="refline"> </span>
<p>
{{r.description}}
</p>
</a>
</div>
</div>
Everything works well except <a>. I have an url type which sometimes is _blank sometimes _self etc. So, sometimes it will be router link and sometimes external link (that's why I'm not using routerLink).
When I click on the link it's doing full post back in new page when it's _blank and that's ok but when it's _self browser is doing post back in the same page.
How can I rectify this mistake?
Use attribute data binding:
<a [href]="r.url" [attr.data-target]="r.urlType" class="reforms-1">
This should work.
You need to use a routerLink. A plain <a href="..."> is handled by the browser, not by Angular.
<div class="row">
<div class="col-sm-3" *ngFor="let r of ref">
<a *ngIf="r.urlType !== 'routerLink'" [href]="r.url" [target]="r.urlType" class="reforms-1">
<img class="refimg" [src]="r.image" alt="">
<span class="reftitle"><h4>{{r.title}}</h4></span>
<span class="refline"> </span>
<p>
{{r.description}}
</p>
</a>
<a *ngIf="r.urlType == 'routerLink'" [routerLink]="r.url"> ... </a>
</div>
</div>
<li ng-repeat="address in search.result.addresses">
<a href ng-click="selectAddress(address)">
{{address.addressLines}}
</a>
</li>
The problem is with my {{address.addressLines}}
This is currently a string array so my value on screen is printed out like
["address1","address2","address3","address4"]
But I just want it printed like
address1,address2,address3,address4
There are fundamentally 2 ways:
1) By using native angular directives:
<span ng-init="foo=[1,2,3,4]" ng-app="app">
<span ng-repeat="f in foo">{{f}}<span ng-if="!$last">,</span></span>
</span>
2) By writing a simple filter (best way):
angular.module('app', []).filter('arrayToList', function(){
return function(arr) {
return arr.join(',');
}
});
<p>{{foo|arrayToList}}</p>
This is the working example on jsfiddle: http://jsfiddle.net/g0dmazzk/
You can do this using join also :
<li ng-repeat="address in search.result.addresses">
<a href ng-click="selectAddress(address)">
{{address.addressLines.join()}}
</a>
</li>
I thing somthing like this would work...
<li ng-repeat="address in search.result.addresses">
<a href ng-click="selectAddress(address)">
<span ng-repeat="a in address.addressLines"> {{a}},</span>
</a>
</li>
To avoid dealing with the comma in the last item on the list, I used a class (label from Bootstrap) like this:
<span ng-repeat="a in address.addressLines" class="label label-default"> {{ a }} </span>