Using *ngFor values in component method - html

hey im trying to get the id value from *ngFor loop into a method in my component in order to delete a specific object
my code looks like that:
html:
<tr *ngFor="let c of myCompanyArray">
<td>{{c.id}}</td>
<td>{{c.companyName}}</td>
<td>{{c.password}}</td>
<td>{{c.email}}</td>
<td>
<a href="" class="tooltip">
<i class="fas fa-user-edit"></i>
<span class="tooltiptext">edit company</span>
</a>
</td>
<td>
<a class="tooltip" >
<i class="far fa-trash-alt" (click)="sendIdForDelete({{c.id}})"></i>
<span class="tooltiptext">delete company</span>
</a>
</td>
</tr>
Component:
sendIdForDelete(compid){
console.log("company id is : " + compid.value);
///this.dataService.deleteCompany(compid.value);
}
what ever syntax i tried inside (click)="sendIdForDelete({{c.id}}) or (click)="sendIdForDelete(c.id)" i always get undefined
really appreciate your help thanks

You should call sendIdForDelete(c.id) in you'r html and change you'r method in you'r component like below
sendIdForDelete(compid: number){
console.log("company id is : " + compid);
}
In this case you are passing id ( which is number or string ) to you'r component (.ts file ) and you'r function (sendIdForDelete) should get just an id.
Now you can do anything with the corresponding id in function.

You should not use interpolation in your template, just do without {{}},
<i class="far fa-trash-alt" (click)="sendIdForDelete(c.id)"></i>
and inside TS do not use value, because you are already passing a number,
sendIdForDelete(compid:any){
console.log("company id is : " + compid);
}

Related

Object Tag not functionating properly with image and pdf files in angular

I am working on a project where I need to show images in an accordion manner but this image can be of any type. Either jpeg, png, pdf or even excel. So to showcase as much as possible we have used <object> in which we are passing link to data. But somehow I am not getting the image or pdf iver hear in accordion.
HTML :
<table>
<tr class="table_rows" *ngFor="let row of operationsTableData;let i = index" (click)="onOperationRowClicked(row,i)" [ngClass]="{'active' : activeRow !== null && (i === activeRow)}">
<td class="oper_row">{{row.OPRSEQUENCENO}}</td>
<td class="oper_row">{{row.CKEY}}</td>
<td class="oper_row">{{langFlag == 'en' ? row.Status.en : row.Status.fr}}</td>
</tr>
//Some more code here
</table>
<div class="img_container">
<div id="myCarousel" *ngIf="imageList.length" class="carousel slide" data-ride="carousel" data-interval="false">
<div class="carousel-inner">
<div class="item" *ngFor="let element of imageList;let i=index" [ngClass]="{'active': i==0}">
<object [data]="element.sanitizedUrl" [ngClass]="{pdf_resize: element.type=='pdf'}" >
<div class="doc_unsupported">Document type not supported.
Please click the above icon to download.</div>
</object>
<div class="overlay_absolute_div" (click)="openItem(element.FILE_PATH)"><i class="fa fa-external-link" aria-hidden="true"></i></div>
</div>
</div>
<a class="left carousel-control active" href="#myCarousel" data-slide="prev">
<span class="fas fa-chevron-left" style="color: white;"></span>
</a>
<a class="right carousel-control active" href="#myCarousel" data-slide="next">
<span class="fas fa-chevron-right"style="color: white;"></span>
</a>
</div>
</div>
TS file code
this.operationsTableData.forEach(element => {
if(element["AttachmentsDetail"]) {
element["AttachmentsDetail"].forEach(file => {
file['FILE_PATH'] = `http://${window.location.hostname}:${window.location.port}/chronos/workbookModal/operationFile${file['FILE_PATH']}`
file['sanitizedUrl'] = this.sanitizer.bypassSecurityTrustResourceUrl(file['FILE_PATH'])
});
}
element['Images']= element["AttachmentsDetail"] && (element["AttachmentsDetail"]).length ? (element["AttachmentsDetail"]).filter(value => value.forCarousel == 1) : [];
});
Here as you can see we are using sanitized URL because we are running it onver http and the server from where the images are coming is different. The point over here is when we are directly binding the same URL or work it with iframe it is working fine. But when we are trying to do the same with <object> tag, that time it is now giving anything except blank space. Am I missing something?
Turn out to be when you are using an <object> tag and you are using dynamic values under [data] than that time you need to reload the component. If you are getting data in ngoninit and binding it directly then it will work properly but when you are getting data on change event that time it is not rendering the [data] value. So we simply passed <object> tag from ts file and it started working correctly.
onOperationRowClicked(row,index) {
this.selectedOperation = row
this.imageList = this.selectedOperation.Images
setTimeout(() => {
this.imageList.forEach((element, index)=>{
var object = document.getElementById(`obj-${index}`);
var object2 = document.getElementById(`iconno-${index}`);
object.innerHTML = `<object data="${element.FILE_PATH}"
[ngClass]="{pdf_resize: element.type=='pdf'}" >
<div class="doc_unsupported">Please select the Operation Row to see the image / pdf file</div>
</object>`
object.appendChild(object2)
})
}, 0);
}
This might not be the correct way to do it but atleast I got the solution which I wanted.

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>

ng repeat does not return variable from JSON file

I have the following html code that belongs to a template in AngularJS framework:
<ul class="sb-parentlist">
<h1 class={{headerClass}}> Popular</h1><div data-ng-repeat="data in data track by $index">
<li>
<span class="sb-text-title" href="#" ng-click="openFaq = ! openFaq"><b>{{data[$index].faq.frage |translate}}</b></span>
<span ng-show="openFaq" class="sb-text">
<br>
{{data[$index].faq.antwort |translate}}
</span>
</li>
</div>
</ul>
I am getting the number of "li" elements on my browser correctly on printing the results, but the variables are not defined as they should be, blank entries appearing.
here is the JSON entry:
{
"faq":
{"frage":"HB_START_FAQ_Q",
"antwort":"HB_START_FAQ_A"}
,
"screencast":"HB_START_SCREENCAST"
},
{
"faq":
{"frage":"HB_START_FAQ_Q_1",
"antwort":"HB_START_FAQ_A_1"}
,
"screencast":"HB_START_SCREENCAST_1"
},
{
"faq":
{"frage":"HB_START_FAQ_Q_2",
"antwort":"HB_START_FAQ_A_2"}
,
"screencast":"HB_START_SCREENCAST_2"
},
{
"faq":
{"frage":"HB_START_FAQ_Q_3",
"antwort":"HB_START_FAQ_A_3"}
,
"screencast":"HB_START_SCREENCAST_3"
}
I am interested to get the nested item. Any ideas?
Because data is ambiguous between the collection name and the item being iterated over - change your ngRepeat syntax:
data-ng-repeat="item in data track by $index"
And use item[$index]. Im not entirely sure why you aren't just doing data.faq - you need to select by the $index

Angular JS Display String Array From Json

<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>

Angular JS shows HTML within the tag

I am trying to insert HTML inside template using ng-bind-html-unsafe attribute. But for some reason its not working.
My code:
<tr class="white two-button" ng-repeat="(key,value) in recommendations | ojoScoreFilter:ojoScore | relevancyScoreFilter:relevancyScore | orderBy:predicate:reverse">
<td>
<div ng-bind-html-unsafe="value.button"></div>
</td>
</tr>
I am not able to see the HTML.
If I change ng-bind-html-unsafe="value.button" to ng-bind-html-unsafe="{{value.button}}" then it shows HTML but within the attribute, something like this:
<div ng-bind-html-unsafe="<a class="action_hrefs full-width bgcolor10 purple-hover flat-button flat-white-button btn" data-value="947" href="#"><i class="fa fa-lock"></i> Unlock</a>"></div>
Ok I found solution for this:
JS:
$scope.renderHtml = function(html_code)
{
return $sce.trustAsHtml(html_code);
};
HTML:
<p ng-bind-html="renderHtml(value.button)"></p>
make a filter like this
.filter('trusted',
function($sce) {
return function(ss) {
return $sce.trustAsHtml(ss)
};
}
)
and apply this as a filter to the ng-bind-html like
<div ng-bind-html="code | trusted">