Angular 2 a href target - html

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>

Related

Have link click trigger unique toggle button?

I am using AngularJS and just CSS/HTML to create this webpage. I have a list of book links that I loop through and create a new 'card' (just creating a div) for each link. As part of this loop, I am also creating a toggle so that each card has a toggle switch next to it. I want the toggle to be switched on/true when the book link is clicked but right now it only seems to work for the first link as I want. If I click any other link in the list, the toggle doesn't seem to be working.
I essentially have it set up so that when the link is clicked, it triggers toggleSwitch() function which goes and toggles the button. I think the problem is that the way I have my angular written is so that it looks for the first link every time, but I'm not sure how to loop through the list. (I am new to web development so forgive me if this seems dumb)
<span *ngIf="selectedTitles">
<div *ngFor="let audibleTitle of selectedTitles" class="justify-content-center">
<a class="bookLink" href="link to a book" (click)="toggleSwitch()" target="_blank">
<div class="audible-title card-body">
<strong>title name</strong> <br>
title author <strong> | </strong>
<!--<span *ngFor="let genre of audibleTitle.genre"> {{genre}} > </span>-->
<span>title genre</span>
</div>
</a>
<label class="switch">
<input #link type="checkbox" id="sliderButton" >
<span class="slider round" ></span>
</label>
</div>
</span>
export class ContentRecommendationComponent implements OnInit {
#ViewChild('link') testLink;
#Input() prometheusResponse: PrometheusResponse;
selectedTitles: AudibleTitle[] = [];
constructor() {
}
ngOnInit() {
}
toggleSwitch(){
this.testLink.nativeElement.checked = true;
console.log('this is showing');
}
}
I want every toggle to be associated to it's correct link. I guess my question is how do I link through every link in angular?
One way would be to send the link template variable through your toggleSwitch method like this:
<span *ngIf="selectedTitles">
<div *ngFor="let audibleTitle of selectedTitles" class="justify-content-center">
<a class="bookLink" href="link to a book" (click)="toggleSwitch(link)" target="_blank">
<div class="audible-title card-body">
<strong>title name</strong> <br> title author <strong> | </strong>
<!--<span *ngFor="let genre of audibleTitle.genre"> {{genre}} </span>-->
<span>title genre</span>
</div>
</a>
<label class="switch">
<input #link type="checkbox" id="sliderButton" >
<span class="slider round" ></span>
</label>
</div>
</span>
Now your toggleSwitch would be like this:
toggleSwitch(link){
link.nativeElement.checked = true;
console.log('this is showing');
}
In this way, in each iteration, toggleSwitch will receive the actual link in that iteration, and only that specific switch will be toggled
I want every toggle to be associated to it's correct link. I guess my question is how do I link through every link in angular?
You need to pass the iterator index of the loop to the toggle function. *ngFor="let item of items; let i=index" then pass i to toggleswitch(i).
I don't advise accessing the HTML nativeElement for something like this. You already have an underlying data structure, so you can add a checked property to this instead. You are having problems with only being able to check the first link because you are not telling your toggleSwitch() method which audibleTitle you want to check or uncheck. Think about the underlying data model, not the HTML itself.
I also question your use of a (click) action on a link which also has a href. If the link is clicked twice (thereby opening a second window), you will unset its checked property. Just food for thought.
In your TypeScript:
export interface AudibleTitle {
checked: boolean;
link: string;
}
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
audibleTitles: Array<AudibleTitle> = [
{
checked: false,
link: `https://example.com`
},
{
checked: false,
link: `https://google.com`
},
];
toggleSwitch(audibleTitle: AudibleTitle) {
audibleTitle.checked = !audibleTitle.checked;
console.log('this is showing');
}
}
audibleTitles: Array<AudibleTitle> = [
{
checked: false,
link: `https://example.com`
},
{
checked: false,
link: `https://google.com`
},
];
toggleSwitch(audibleTitle: AudibleTitle) {
audibleTitle.checked = !audibleTitle.checked;
console.log('this is showing');
}
}
In your HTML:
<span *ngIf="selectedTitles">
<div *ngFor="let audibleTitle of selectedTitles" class="justify-content-center">
<a class="bookLink" href="https://example.com/{{audibleTitle.link}}" (click)="toggleSwitch(audibleTitle)" target="_blank">
<div class="audible-title card-body">
<strong>title name</strong> <br>
title author <strong> | </strong>
<!--<span *ngFor="let genre of audibleTitle.genre"> {{genre}} > </span>-->
<span>title genre</span>
</div>
</a>
<label class="switch">
<input #link type="checkbox" id="sliderButton">
<span class="slider round"></span>
</label>
</div>
</span>

Cannot read property '0' of undefined in angular 6

I'm getting this error in console, Cannot read property '0' of undefined but still I'm getting the result as expected.
This is my HTML code
<div class="col-md-3">
<div class="slider-product">
<a href="#">
<img src="{{featureProducts[0].img_path}}" alt="Image" style="max-width:100%;">
<span class="tag">{{featureProducts[0].cat_name}}</span>
<div>
<a class="title">{{featureProducts[0].name}}</a>
</div>
<div class="price">
<i class="fa fa-inr"></i> {{featureProducts[0].min_price}}
</div>
</a>
</div>
</div>
Here is the function in typescript file
getFeatureProducts(){
this.httpClient.get(this.baseUrl+`/getFeatureProducts`)
.subscribe(
(data:any[]) => {
if(data.length) {
this.featureProducts = data;
}else{
this.featureProducts = null;
}
}
)}
featureProducts is declared inside the class as
featureProducts: any;
I know there is work around to this problem, like I can use multiple variables as below
in typescript
imgpath0 = this.featureProducts[0].imgPath;
And using this variable in html directly as
{{imgPath0}}
But this is not a better approach as I have lot of properties to be displayed in html and I cannot declare as many variables in ts.
Note: I don't want to loop using 'for' in html. Instead I need to fetch the properties as we usually do in JSON.
You can use *ngIf="featureProducts && featureProducts[0]" and prevent rendering the div until featureProducts object gets populated.
<div class="slider-product" *ngIf="featureProducts && featureProducts[0]">
<a href="#">
<img src="{{featureProducts[0].img_path}}" alt="Image" style="max-width:100%;">
<span class="tag">{{featureProducts[0].cat_name}}</span>
<div>
<a class="title">{{featureProducts[0].name}}</a>
</div>
<div class="price">
<i class="fa fa-inr"></i> {{featureProducts[0].min_price}}
</div>
</a>
</div>

routerLink from Object in Angular2

I'm trying to build a "Team Member" page from JSON data.
I can create the page with basic things like firstName, lastName, position.
Each team member has their own page with a little more information
What I cant figure out is how to include the team members url to my [routerLink].
My router link would look like this which I have setup in my routes
<a [routerLink]="['./glenn']">
And this is how I'm attempting to use it
<div class="team-members" *ngFor="let teammember of teammembers" >
<div class="clearfix">
<div class="col-xs-12 col-sm-8 col-md-8 col-lg-6 team-member member-item" style="cursor: pointer;">
<a [routerLink]="['./"{{teammember.firstName}}"']">
<div class="member-pic-holder">
<img alt="" src='{{teammember.photo}}' />
<div class="member-overlay"></div>
</div>
<h4>{{teammember.firstName}}<br/>{{teammember.lastName}} <span class="fa fa-arrow-right"></span></h4>
<p class="company-position">{{teammember.position}}</p>
</a>
</div>
</div>
</div>
Any thoughts on this one please?
It's also breaking when I'm trying to include the team-members photo
<img alt="" src='{{teammember.photo}}' />
However one thing at a time!
Thanks
GWS
You are using the {{ foo.bar }} binding incorrectly, the {{ }} syntax allows you to do one way binding, what you want is to use regular js expressions when binding to your objects properties.
When binding to an html element attribute, you can use the [attr.{id|href|etc}] binding, in your case, for the href of the image you can use:
<img alt="" [attr.href] = 'teammember.photo' />
And for the router, simply use [routerLink] = "[teammember.firstName]" (not sure why you need the ./, if you do need it, you could append it using a getter on your team member class, as shown bellow.
For your routes, you could do something along the lines of:
Team Member Class
export class TeamMember {
// ...properties and constructor
private memberUrl: string = "foobar"
get MemberRoute(){
return `./${this.memberUrl}`;
}
}
Template:
<div class="team-members" *ngFor="let teammember of teammembers" >
<div class="clearfix">
<div class="col-xs-12 col-sm-8 col-md-8 col-lg-6 team-member member-item" style="cursor: pointer;">
<a [routerLink]="[teammember.MemberRoute']">
<div class="member-pic-holder">
<img [attr.href] = 'teammember.photo' />
<div class="member-overlay"></div>
</div>
<h4>{{teammember.firstName}}<br/>{{teammember.lastName}} <span class="fa fa-arrow-right"></span></h4>
<p class="company-position">{{teammember.position}}</p>
</a>
</div>
</div>
</div>
Hope this helps!
can you try like this:
['./',teammember.firstName]
for img use
<img alt="" [src]="teammember.photo" />

how to select child element in my test case

I am trying to test a click event for my html
html
<div class="testGroup">
<div ng-repeat="test in tests">
<a ng-click="clickMe(test.id)">{{test.name}}</a>
<a ng-click="clickMe(test.id)">{{test.name}}</a>
<a ng-click="clickMe(test.id)">{{test.name}}</a>
<a ng-click="clickMe(test.id)">{{test.name}}</a>
</div>
</div>
<div class="testGroup">
<div ng-repeat="test in tests">
<a ng-click="clickMe(test.id)">{{test.name}}</a>
<a ng-click="clickMe(test.id)">{{test.name}}</a>
<a ng-click="clickMe(test.id)">{{test.name}}</a>
</div>
</div>
<div class="testGroup">
<div ng-repeat="test in tests">
<a ng-click="clickMe(test.id)">{{test.name}}</a>
<a ng-click="clickMe(test.id)">{{test.name}}</a>
<a ng-click="clickMe(test.id)">{{test.name}}</a>
</div>
</div>
Three divs are identical but I want to select the first testGroup class and click the first a tag. I also want to click the first a tag on the second testGroup class.
In my spec.js
element.all(by.css('.testGroup')).get(0).then(function(elem) {
element(by.repeater('test in tests').row(0)).click();
});
I am getting undefined is not a function error. I think it's because the get(0) is not a promise. How do I trigger click on the first a tag in the first testGroup div and first a tag in second testGroup div? Thanks for the help.
Would something like this work alright?
var testGroupOneTag = $$('.testGroup').get(0).$('[ng-click="clickMe(test.id)"]');
var testGroupTwoTag = $$('.testGroup').get(1).$('[ng-click="clickMe(test.id)"]');
testGroupOneTag.click():
testGroupTwoTag.click():
$$ is short for element.all by css.
There is no then() on an ElementFinder anymore (since 2.0).
Chain element and element.all(), use by.repeater() and column():
var testGroups = element.all('.testGroup');
var testGroupOneTag = testGroups.first().element(by.repeater("test in tests").column("test.name"));
var testGroupTwoTag = testGroups.get(1).element(by.repeater("test in tests").column("test.name"));
testGroupOneTag.click();
testGroupTwoTag.click();

Code in editor looks fine, in browser it changes

I have this weird problem.
When i wrap a anchor tag around a div, the html markup completely changes.. cleared cache and everything.
Its about the anchor with the class outgoing link
Html in the code editor (correct code):
<a class="outgoing-link" href="#">
<div id="content-element">
<div class="top-info">
<span class="title-provider">Vodafone</span>
<img src="phone-placeholder.png"
alt="placeholder"
width="58px"
height="50px"/>
<div class="bg-circle"></div>
<span class="dur-discount">1e 3 maand</span>
<span class="price-discount">€ 16,50</span>
<span class="dur-normal">Daarna</span>
<span class="price-normal">€ 20,00</span>
</div>
<h3>iPhone 4GS abonnement</h3>
<p><span>100</span> min & sms <span>500</span> mb</p>
<p><span>2 jr</span>telefoon abonnement</p>
<p>Prijs telefoon: <span>Gratis</span></p>
<div class="hover-extra-info">
<p>Aansluitkosten: <span>€ 24,95</span></p>
<p>Vodafone abonnement</p>
<p>aanbieder: Student Mobiel</p>
<p>Totale kosten over 2 jaar</p>
<p>€ 547,22</p>
</div>
</div><!-- end content-element-->
</a>
Code in the browser:
<a class="outgoing-link" href="#"></a>
<div id="content-element">
<a class="outgoing-link" href="#">
<div class="top-info">
<span class="title-provider">Vodafone</span>
<img src="phone-placeholder.png"
alt="placeholder"
width="58px"
height="50px"/>
<div class="bg-circle"></div>
<span class="dur-discount">1e 3 maand</span>
<span class="price-discount">€ 16,50</span>
<span class="dur-normal">Daarna</span>
<span class="price-normal">€ 20,00</span>
</div>
</a>
<h3>iPhone 4GS abonnement</h3>
<p><span>100</span> min & sms <span>500</span> mb</p>
<p><span>2 jr</span>telefoon abonnement</p>
<p>Prijs telefoon: <span>Gratis</span></p>
<div class="hover-extra-info">
<p>Aansluitkosten: <span>€ 24,95</span></p>
<p>Vodafone abonnement</p>
<p>aanbieder: Student Mobiel</p>
<p>Totale kosten over 2 jaar</p>
<p>€ 547,22</p>
</div>
</div><!-- end content-element-->
It adds another link and puts them at the wrong places.
Any ideas as to what's going on? Or am i just missing something.
Any help would be appreciated :)
i think its because nested anchor tags are illegal
see: http://www.w3.org/TR/html401/struct/links.html#h-12.2.2
it should be easy to do without the nested anchor tag while keeping the functionality the same.
Could be a try to automatically fix invalid HTML ( => Quirksmode ?), as an achor-tag should not contain -Tags.
Try to add a DOCTYPE statement at the beginning of the file, does that change the behavoir?
The Doctype-Statement (must be on the first line HTML file / output) could be like this:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
"http://www.w3.org/TR/html4/loose.dtd">