Find an element by its id in the html file - javascript

I have an array
items = [{
"id" : 1,
"name": "peter"},
{
"id" : 2,
"name": "john"}
...
]
I am trying to find an item in the html file by the id based on that, I am trying to hide and element.
It can be easily done in js file, but I am trying to see if there is an easy way to do it in html file

If you want to hide an item, lets say its index is 2, you can do something like this in the HTML
<ng-container *ngFor="let eachItem of allArrayItems; let index=i">
<div *ngIf="i != 2"> // This ngIf will be hidden if the index is 2
whatever logic
</div>
</ng-container>

You can add a template selector to the element
<input #myElement>
Then you can add a reference in your ts file
#ViewChild('myElement') myInput: ElementRef<HtmlInputElement>;
Or even reference the element directly in the template
<button (click)="myElement.focus()"></button>
https://angular.io/api/core/ViewChild
https://angular.io/api/core/ElementRef

Related

Why nested array dynamic update is not working in my case

Hi i have a problem with nested array dynamic update as shown in below image
Here is a steps to re-produce the problem
click on Add Likes button it will add likes for eg New Apple
my default like is Mango
click on Add about button it will add next row (Mango is not appeared) click on Add Likes to see the problem.
For reducing code readability i have put helper function into a mixin file called mixin.js
Expectation: i can add any number of Add about and Add Likes(with default value Mango)
Here is my code: https://codesandbox.io/s/musing-hawking-di4d3?file=/src/App.vue
First, you don't need a nested array for the tags property.
Use:
getLikesTemplate() {
let year = this.year;
let template = {
id: this.getUniqueId(),
like: `I'm ${year} Old and like things like`,
tags: [this.getTagsTemplate("Mango")] //nesting removed
};
this.year++;
return template;
}
Secondly, in JS objects are passed by reference, so you can do this:
method:
addLikes(like) { //removed the extra code
like.tags.push(this.getTagsTemplate("New Apple"));
},
template:
...
<div style="text-align: left; display: flex">
<div> //nesting removed
<div class="tags" v-for="tag in like.tags" :key="tag.id">
{{ tag.name }}
</div>
</div> //passing the reference to the object
<button style="margin-left: 20px" #click="addLikes(like)">
Add Likes
</button>
</div>
Result img

Vue how to send index from v-for to method

I'm trying to pass the index of a v-for so i can change some values, i'm adding the doctor team members dynamically and i have this file input to add their image, although when i add doctors it only changes the first's one image because it always sends index of the first doctor, the file input is inside the v-for loop if that helps.
<v-file-input
hide-input
class="d-none"
id="doctorImage"
truncate-length="1"
#change="doctorImage($event, index, doctor)"
></v-file-input>
Method:
doctorImage(e, index, doctor) {
console.log(index)
this.doctors[index] = {
image: URL.createObjectURL(e),
imageData: e,
name: doctor.name,
specialty: doctor.specialty
}
this.doctorChange += 1
}
The index is always 0, although it displays the index number when i create it dynamically on the doctor's card, why is that happening?
Refer List Rendering using v-for.
<div ... v-for="(doctor, index) in doctors" ... >
{{ index }} // you can use index
...
</div>
Ok so i fixed the issue, that happened because i had a label for doctorImage and the file input id was doctorImage also inside the v-for statement, that made multiple same id's and created a conflict.
I iterate with a limit. Example
If the data were:
{
limit: 3,
currentIndex: 2,
listData:[{name:'Data1'},{name:'Data2'},{name:'Data3'},{name:'Data4'},{name:'Data5'}]
}
In the .vue file it would be the following
<span v-for="index in limit" v-bind:key="index">
{{listData[index+currentIndex].name}}
</span>
I make sure that you control that the sum index + currentIndex does not exceed the limit of your data

Can I make an attribute appear only once in a vue v-for

I have an array of people with associated teams. I want to display all the people in the record, but I only want to display their team name once.
Meaning, if the v-for loop has encountered this particular team name, it should put it in a new temporary array to signify that it should be unique, then when it encounters that team name again, checks it through that temporary array and prevent it from showing again.
Sample HTML Code:
<div id="a-list">
<div v-for="person in people">{{person.Name}}, {{person.Team}}</div>
</div>
Sample Vue Code:
var crew = new Vue({
el: "#a-list",
data: {
people:
[ { "Name": "Richard","Team":"DMS"}, { "Name": "Mark","Team":"VV"}, { "Name": "Steve","Team":"VV"}, {"Name":"Koji","Team":"MZ"}, {"Name":"Jamie","Team":"VV"} ]
}
});
Expected Output:
Richard, DMS
Mark, VV
Steve,
Koji, MZ
Jaimie,
Is this possible to do directly from the v-for loop and not in the JS file?
Edited to show more data that are not sequential
Update: As Fabio has pointed out, the above scenario wouldn't make much sense unless the order of the team is arranged sequentially in the output first. So his answer is correct.
This could be a solution:
<div id="a-list">
<div v-for="(person,index) in people"> {{person.Name}}, {{ ((index == 0) || person.Team != people[index-1].Team) ? person.Team : '' }}</div>
</div>

angular scope variable is not visible inside anchor tag

Hello I am newbie to Angular and tried to call a controller method with a hyperlink by following way:
{{item.contractnum}}
Where item.contractnum is a scope variable which is visible when I pull it out from 'a' tag but inside the tag its not visible, also I want to pass it back to controller method getAssetDetail but can't figure out how to accomplish it. Please suggest.
EDIT:
View:
<tbody>
<tr ng-repeat="item in pagedItems[currentPage] ">
<td>contract number {{item.contractnum}} <br /> Serial Number:{{item.serialNum}} </td>
</tr>
</tbody>
Controller:
$scope.getAssetDetail = function (contractNum) {
//My Code Here
}
pagedItems=[{"contractnum":"123", "serialNum":"ABC1" },
{"contractnum":"121", "serialNum":"ABC2" },
{"contractnum":"124", "serialNum":"ABC3" },
{"contractnum":"125", "serialNum":"ABC4" }
]
if you realy have pagedItems like
pagedItems=[{"contractnum":"123", "serialNum":"ABC1" },
{"contractnum":"121", "serialNum":"ABC2" },
{"contractnum":"124", "serialNum":"ABC3" },
{"contractnum":"125", "serialNum":"ABC4" }
]
so you wrong use ngRepeat, because pass to it simple object like pagedItems[0]
{"contractnum":"123", "serialNum":"ABC1" }
so item in this case is 123,ABC1 that realy don't have property contractnum and others
for solving you can use
ng-repeat="item in pagedItems"
or save in pagedItems arrays of object like [[{},...],[{},...],[{},...]]
or use filter like limitTo for select only needed element in pagedItems
If your pagedItems data is meant to be just for one page of data, then you need to change the ng-repeat line to:
<tr ng-repeat="item in pagedItems">
If your pagedItems data is meant to be all the data for every page, then you need to change your pagedItems data structure to be an object with properties for each page number like:
pageItems = {
"1": [{"contractnum": "121"}, ... etc],
"2": [{"contractnum": "131"}, ... etc]
... etc ...
}
or as an array of arrays where the index in the outer array is the page number (or perhaps pagenumber - 1) and the inner arrays are arrays of objects for each page like:
pageItems = [
[{"contractnum": "121"}, ... etc],
[{"contractnum": "131"}, ... etc]
]
Your existing ng-repeat line should then work.

dynamic id ng-repeat

I am trying to set a dynamic id to my div within my ng-repeat. Let me show an example.
<div id="$index" ng-repeat="repeat in results.myJsonResults">
<div id="$index" ng-click="saveID($index)" ng-repeat="subRepeat in results.myJsonResults.subresults">
</div>
My problem is, when I click on my child div, I want to get my parent id name, but looks like angular doesn't set the ID properly to the div. Is it possible to set a dynamic ID in this concept?
PS: I tried, in the past, create a counter method on my controller and set an index, but it turns out that angular only recognizes the last value of this ID instead.
To answer your question, try this:
<div id="{{$index}}" ...>
While the above should work, this might be not what you want really (!). Please note that this is rather rare with AngularJS to manipulate elements by referring those by id.
You should focus on your model, declarative describe UI and let AngularJS do the rest without doing low-level DOM manipulations "by hand".
A use case I can think of is associating <label> elements with their respective <input> elements, as seen in http://jsfiddle.net/YqUAp/
Applied there is a pkozlowski.opensource's method
<label for="{{ 'textField-' + $index }}">Option {{ $index }}</label>
<input type="text" id="{{ 'textField-' + $index }}" ng-model="field"/>
Though I'm unsure if this is the most effective method. (Even if only for readability)
<div id="{{$index}}" ...>
Works well, but you can also put a dynamic id with the field repeated if - for instance - subRepeat would have an id field.
That would be:
<div id="subRepeat{{subRepeat.id}}" ...>
That will put ids like subRepeat1, subRepeat2, ... on your repeated div
you need to hold the index in your objects
results = { myJsonResults : [
{ name: "abc", id: 1, subResults: [
{ subName: "123", id: 1 },
{ subName: "456", id: 2 }] }
{ name: "xyz", id: 2, subResults: [
{ subName: "789", id: 1 },
{ subName: "098", id: 2 }] }
] };
Also your repeat refers to results, which disconnects them, instead use thisResult:
<div id="thisResult.id" ng-repeat="thisResult in results.myJsonResults">
{{ thisResult.name }}
<div id="subResult.id" ng-click="saveID(subResult.id)" ng-repeat="subResult in thisResult.subResults"> {{ subResult.subName }} </div>
</div>

Categories