For some reason I can't get the value of the list element in the html despite using document.getElementByID and it has the same id. It claims that the element is undefined. Here is the code:
fileupload.component.ts:
ngOnInit() {
var x = document.getElementById('lemons');
if(x){
console.log('it does exits')
x.addEventListener('click', function(e:any){
console.log(x.innerHTML);
});
}
}
fileupload.component.html:
<div class="row" id="filesDisplay">
<div class="col-md-4" id="files">
<li *ngFor="let child of tree" id="lemons">
{{child}}
</li>
</div>
The *ngFor directive is processed after the OnInit hook, so if you want to get an element generated with the *ngFor you should use:
ngAfterViewInit() { }
Also you are duplicating the id, this means it only will select the first element.
lifecycle-hooks angular's guide
Edit: added angular guide
You can not repeat same html id for all the li's. You need to add index to id to diffrentiate.
<div class="row" id="filesDisplay">
<div class="col-md-4" id="files">
<li *ngFor="let child of tree" (click)="test(child)">
{{child}}
</li>
</div>
and in javascript you need to pull the id accordingly.
ngOnInit() {
test(res) {
// perform your logic here..
}
}
You no need to use jquery here where angular is providing all your need in DOM manipulation.
Related
I'm wanting to access each row of my repeater after it's been rendered say from a button click or something similar. Whats the Angular 2 way of doing this?
Thank in advance
<section class="section">
<article class="article" *ngFor="let item of slides; let i = index">
<figure class="figure" *ngIf="item.show">
<img src="{{item.image}}" alt="{{item.description}}"/>
<figcaption>{{item.description}}</figcaption>
</figure>
</article>
<mySlideShow style="display:block;clear:both;" [aList]="slides">click me</mySlideShow>
</section>
Edit:
So I add a public boolean "show" and the initialised it during the ngOnInit() phase. I then have a click event which passes in the object and then I increment by index.
I know this sounds like an obvious one, but just pass the item as a parameter to your (click) method.
<div (click)="onDivClick(item)">Click me!</div>
If you change anything in that item, you probably have to manually call change detection though.
constructor(private changeDetectorRef: ChangeDetectorRef) {}
// ...
onDivClick(item: ISlide): void {
item.description = "some new description";
changeDetectorRef.detectChanges();
}
I know that if I use the directive ng-repeat, like below, I get every element inside and including the div to repeat on the DOM.
<div class="col col-3" ng-repeat="movie in popular" >
<figure>
<img ng-src="{{movie.backdropURL}}" alt="{{movie.code}}">
<div class="overlay"></div>
<figcaption>{{movie.code}}</figcaption>
<!-- <span class="extra-info">{{movie.extra}}</span> -->
<span class="price">{{movie.price}}</span>
</figure>
</div>
However now I want to have some parent elements that won't repeat but will use the same scope object for their children, that will then repeat.
So, I would like to do a repeater that would append the properties of the scope into their parent, something like this:
<ul class="parent1">
<li><img src={{myScope[0].imgUrl}}></li>
<li><img src={{myScope[1].imgUrl}}></li>
<li><img src={{myScope[2].imgUrl}}></li>
</ul>
<div class="parent2">
<span>{{myScope[0].description}}</span>
<span>{{myScope[1].description}}</span>
<span>{{myScope[2].description}}</span>
</div>
I would like to know if it is possible to reuse a native angular directive (I would prefer not to run the same repeater every time for every parent) where it could append the element to the parent. If not, do you have any suggestion for a solution. I've looked up some links for custom directives I haven't succeeded in applying them. So if you have a 'beginners' custom directive tutorial that could help me go on the right direction, it would be highly appreciated.
I don't know if I understand exactly what you are asking for.
Anyway, the ngRepeat directive is placed in the DOM under a particular parent, so you cannot run it once and append the leaves under different parents. The only way to do that is to create a custom directive that runs a loop internally and sets the leaf under the parent of your choice.
That is:
angular
.module('mymodule')
.directive('mydirective', mydirective);
function mydirective(){
var directive = {
restrict: 'A'
, link: link
}
return directive;
function link($scope, elem, attrs) {
for(var i=0;i<$scope.myScope.length;++i){
var el1 = angular.element('<li><img src='+$scope.myScope[i].imgUrl+'></li>'),
el2 = angular.element('<span>'+$scope.myScope[i].description+'</span>');
elem.find('.parent1').append(el1);
elem.find('.parent2').append(el2);
}
}
}
Please let me know if I misunderstood your goal.
Check this:
HTML:
<div ng-app="myApp" ng-controller="myCtrl">
<ul class="parent1">
<li ng-repeat="item in myScope">
<img ng-src={{item.imgUrl}}>
</li>
</ul>
<div class="parent2">
<p ng-repeat="item in myScope"><span>{{item.description}}</span></p>
</div>
</div>
Controller:
angular.module('myApp', [])
.controller('myCtrl', ['$scope', function($scope) {
$scope.myScope = [
{imgUrl:"someUrl1", description: "this is first url"},
{imgUrl:"someUrl2", description: "this is second url"}
]
}]);
Acceptable :) ?
I have a rather sophisticated template for Kendo ListView using knockout-kendo.js bindings. It displays beautifully. My problem is that I need to use the visible and click bindings in parts of the template, but I can't get them to work. Below is a simplified version of my template. Basically, deleteButtonVisible determines whether the close button can be seen, and removeComp removes the item from the array.
<div class='template'>
<div >
<div style='display:inline-block' data-bind='visible: deleteButtonVisible, event: {click: $parent.removeComp}'>
<img src='../../../Img/dialog_close.png'></img>
</div>
<div class='embolden'>#= type#</div><div class='label1'> #= marketArea# </div>
<div class='label2'> #= address# </div>
<!-- more of the same -->
</div>
The view model:
function CompViewModel() {
var self = this;
self.compData = ko.observableArray().subscribeTo("compData");
self.template = kendo.template(//template in here);
self.removeComp = function (comp) {
//do something here
}
}
html:
<div class="row" >
<div class="col-md-12 centerouter" id="compDiv" >
<div class="centerinner" id="compListView" data-bind="kendoListView: {data: compData, template: template}"></div>
</div>
</div>
finally, sample data:
{
type: "Comparable",
marketArea: "",
address: "2327 Bristol St",
deleteButtonVisible: true
},
Take in count that the deleteButtonVisible must be a property on the viewModel linked to the view.You are not doing that right now. The click element can v¡be access from the outer scope of the binding and remove the $parent.He take the method from the viewmodel. Take in count that every thing that you take on the vie must be present on the view model for a easy access.
for example,
<div ng-repeat="item in items">
<p>item.title</p>
...
...
...
<p>item.up</p>
</div>
As i know ,anchor scroll need to specify an id for the anchor, but how can i do the anchor scroll without id, The situation is there's another loop wrap this item repeat. and i can't specify an id like
<div ng-repeat="item in items">
<p id="anchor{{$index}}">item.title</p>
...
...
...
<p>item.up</p>
</div>
So if the code is like below, there will be multi id="anchor{{$index}}"
<div ng-repeat="parent in parents">
<div ng-repeat="item in items">
<p id="anchor{{$index}}">item.title</p>
........
</div>
</div>
And i don't want to use two indexs to specify the id, or the code will be too complex.
How can i solve it .....Thanks
Without knowing your exact scenario, I would say that you are going to have to artificially create some kind of unique anchorId on the elements you care about.
Again, I don't know what your controller or model look like, but you could use a technique similar to this.
angular.forEach(this.parents, function(parent, i){
//Add unique anchorId to parent
parent.anchorId = "anchor-" + i;
angular.forEach(parent.children, function(child, j){
//Add anchorId to child as well
child.anchorId = "anchor-" + i + "-" + j;
});
});
This will basically give you something you can bind to in the DOM and then trigger a scroll with a click event. The bindings would be similar to what you have above.
<div data-ng-repeat="parent in ctrl.parents">
<h1 id="{{parent.anchorId}}">{{parent.name}}</h1>
<div data-ng-repeat="child in parent.children">
<h2 id="{{child.anchorId}}" class="child">
{{child.name}}
<small>
<a href="" ng-click="ctrl.scrollTo(parent.anchorId)">
| to {{parent.name}}
</a>
</small>
</h2>
</div>
</div>
And finally in your controller you could create a scrollTo method that looked something like this.
Ctrl.prototype.scrollTo = function(anchorId){
this.$location.hash(anchorId);
this.$anchorScroll();
};
This will basically do what you want and allow you to scroll around to your hearts content.
I've wrapped all this up in a jsFiddle example so you can see the full working example.
Code
<ul>
{% for item in lis %}
<li>
<div id="single-toggle">|Toggle|</div>
<div class="visible-when-folded">
<div class="name">{{ item.name }}</div>
<div class="date">{{ item.date }}</div>
</div>
<div class="invisible-when-folded">
<div class="about">{{ item.about }}</div>
<div class="contact_info">{{ item.contact_info }}</div>
</div>
</li>
{% endfor %}
</ul>
Example output code
|Toggle|
Peter
24-04-1990
A friendly guy
0474657434
|Toggle|
Martha
22-02-1984
An amazing gal
0478695675
|Toggle|
William
12-11-1974
An oldie
0478995675
Desired behavior
I would like that whenever you click on |Toggle| the about(e.g. A friendly guy)
and contact_info(e.g. 0474657434) part dissapear/reappear.
Attempt at solution
$(function(){
$("#single-toggle").click(
function(){ $("div.invisible-when-folded").toggle(); } );
});
But unfortunately this toggles the fields for each item in the list as opposed to only the one I click on.
Edit
views.py
from django.shortcuts import render_to_response
from django.template import RequestContext
def toggle(request):
lis = [{'name':'Peter', 'date':'24-04-1990', 'about':'A friendly guy',
'contact_info':'0474657434' },
{'name':'Martha', 'date':'22-02-1984', 'about':'An amazing gal',
'contact_info':'0478695675' },
{'name':'William', 'date':'12-11-1974', 'about':'An oldie',
'contact_info':'0478995675' }]
return render_to_response('page.html', {'lis':lis},
context_instance=RequestContext(request))
You need to pass the current object as context in the selector to get the element related to event source object. You also need to use class instead of id or generate unique ids for div with id = single-toggle as html elements are supposed to have unique ids.
Live Demo
I have give the div with id a class="single-toggle"
Change
$("div.invisible-when-folded").toggle();
To
$("div.invisible-when-folded", this).toggle();
You code
$(function(){
$("#single-toggle").click(
function(){ $("div.invisible-when-folded", this).toggle(); } );
});
You need to focus the function on the div within the clicked div... The actual code you need to use is:
$(function(){
$("#single-toggle").click(
function(){ $("div.invisible-when-folded", this).toggle(); } );
});