I want to create dynamic ng-reapet and push the array element on click event:
my controler code is
$scope.AddlistItem = function (index) {
$scope.selecttaglist($scope.tag);
};
$scope.selecttaglist = function (tag) {
//var i=$scope.selectedTags.length;
angular.forEach($scope.selectedTags,function(tag,index){
console.log(tag.name);
$scope.selectedTagslist.push(tag);
})
And View Code:
<ul id="boxElement" ><li ng-repeat="tag in selectedTagslist" ng-controller="ItemController" ng-bind="tag.name" ></li></ul>
Html Code
<div class="AddButtn" id="aDD{{item.name}}" ng-controller="ItemController" ng-click="AddlistItem()" ></div>
problem is that when i clicking on link. array element are pushing on all ng-reapet element.i want array will be push only on clicked element container. iam not sure my approach is write or wrong for doing this. i am new in angularjs. anyone can help on this.
If the model for ng-repeat is the same then you need different approach as model drives the view so i.e. you will need more than one
<ul id="boxElement" ><li ng-repeat="tag in selectedTagslist" ng-controller="ItemController" ng-bind="tag.name" ></li></ul>
<ul id="boxElement" ><li ng-repeat="tag in selectedTagslist2" ng-controller="ItemController" ng-bind="tag.name" ></li></ul>
with a copy of the first element - angular.copy otherwise the object will be connected by reference and the effect will be same
hope that makes sense
Related
I'm building a todo list with nested lists. List items are attached to their respective unordered lists with the use of Handlebars templating. The list items each contain a text input to represent them in the browser, empty <ul></ul> tags for any future child list items, and a button to add those list items. This works, and the text inputs appear properly in the DOM. However, when I attempt to retrieve newly added <li></li> elements via e.target beyond the master list, nothing is detected in the child lists, despite the fact that they all appear in the DOM.
In the code, I have an event handler bound to the button which adds a new list item for each list. In this case, e.target is the button. My aim is to use jQuery's .focus() on the new item's input so the cursor is already there when it appears. I have tested out using both jQuery and vanilla JS methods in console.log() to traverse the tree, going through the button's sibling-level <ul></ul> but this does not appear to be a problem with traversal methods, as the lists are always logged, though empty.
In this scenario, one item is present on the master list. Subsequently, one item is added to the first sublist via the event handler function for the "new list item" button (which itself is inside the first item's <li></li> tags). Inside that function, I traverse the tree to access the list item's child unordered list and log the result to the console, as with the following:
console.log(e.target.closest('li').querySelector('ul'));
The returned result shows that the list is empty:
<ul id="list-2" class="parent-list">
</ul>
However, the newly appended list item is clearly visible in the DOM:
<ul id="list-2" class="parent-list">
<li data-id="...">...</li>
</ul>
The relevant HTML including script for list templating with handlebars:
<body>
<label><input type="checkbox" id="toggle-all-checkbox">Toggle All</label>
<br>
<button class="add-parent-list-todo">+</button>
<br>
<ul id="list-1" class="parent-list">
</ul>
</body>
<script id="todo-list-template" type="text/x-handlebars-template">
{{#this}}
<li {{#if completed}} class="completed" {{/if}} data-id="{{id}}">
<input class="todo-input" type="text" value="{{text}}">
<div id='options'>
<button class="delete">x</button>
<input type="checkbox">
</div>
<br>
<button class="add-parent-list-todo">+</button>
<br>
<ul id="{{childList}}" class="parent-list">
</ul>
</li>
{{/this}}
</script>
The event handler function in question:
enterTodoText: function (e) {
var parentList = $(e.target).next().next().attr('id');
this.todos.push({
text: '',
id: util.uuid(),
completed: false,
parentList: parentList,
childList: "list-" + childListId
});
childListId++;
this.render();
$(e.target).next().next().children('li:last-child').find('.todo-input').focus();
console.log(e.target.closest('li').querySelector('ul'))
}
I'd very much appreciate any insight anyone might have.
I have come to realize that this in overwhelming likeliness has something to do with e.target being inside of a Handlebars template. Using e.target from a template, I am seemingly unable to traverse beyond the template itself. This is confirmed by testing with console.log($(e.target).parents()), which shows that for sublists, the topmost detectable parent is <li> (which is the parent element in the template), when I expected it to be <html>.
The solution I came to is to just traverse the tree using $('body') as the starting point, as opposed to $('e.target').
I don't want to change HTML because I want to leave the display the way it is for default view and want to move them in second view. I want to know how I can dynamically order the class of a div.
I want to do this via button click. I have adEventListener() for 'click' where I am doing something and the move logic would go inside this event listener.
I understand that I can get these divs, remove from their parents and place it where I want. But I do not know how to do these for each of them since I have multiple lis. I am struggling with the loop so that I can do these for each li. I need to do this using pure JS and not jQuery.
<ul>
<li>
<div>
<div class="a">
<div class="b">
<a class="c">
<div class="d"></div>
<div class="e">
<div class="f"></div> // this is the first item that I want to move
</div>
<div class="g"></div> // this is the second item that I want to move
</a>
</div>
<div class= "h"></div> // I want above mentioned divs to be before this div
</div>
</div>
</li>
//There are multiples lis
<li></li>
Assuming you would like to do this on load of the page, you could solve your problem with the following JQuery DOM manipulations:
$(document).ready(function(){
$("ul .a").each(function(index, element){
$current_div_a = $(element);
$div_h = $current_div_a.find(".h");
$div_f = $current_div_a.find(".f");
$div_f.clone().insertBefore($div_h);
$div_f.remove();
$div_g = $current_div_a.find(".g");
$div_g.clone().insertBefore($div_h);
$div_g.remove();
})
});
You can test it out on this demo.
I strongly advise against this way of doing it though. I guess it's also the reason why your question got some downvotes too. Just modifying your HTML keeps your code clean, maintainable and clearer for anyone else starting to work on your project. Keeping backwards compatibility for your code as much as possible will cause maintainability problems later.
I ended up using
var list = document.querySelectorAll("ul li");
for (var item of list) {
let fClass = item.querySelector(".f");
fClass.parentNode.removeChild(fClass);
let parentOfFirstChildAfterWhichIwantMyF = item.querySelector(//selector for parentOfFirstChildAfterWhichIwantMyF);
parentOfFirstChildAfterWhichIwantMyF.insertAdjacentElement("beforeend", fClass);
}
I want to show/hide a new div if any of the user links clicked:
<ul id="pm-tabs">
<li v-for="user in unreadMsgsList">
<a #click="openPMbox(user)"> ${user}</a>
</li>
</ul>
the method is:
openPMbox: function(user) {
this.isPmBoxOpenList[user] = !this.isPmBoxOpenList[user];
},
the user data is stored at isPmBoxOpenList: [] and I can verify that it is properly filled.
The window that should show/hide is like this and is out of v-for loop above:
<div class="pmbox" v-bind:disabled=="isPmBoxOpenList" >Some Text </div>
But I get error at template. Not sure how should I define pmbox so appreciate your hints.
P.S. It worths mentioning user is not define in data. It is only an object in isPmBoxOpenList array.
You can use v-if, to display or hide like this:
<div class="pmbox" v-if="isPmBoxOpenList[user]" >Some Text </div>
I wana toggle elements but not all elements i need just one on which is clicked.
for example if I have 3 form elements and 3 buttons if I click on button 1. I just wana toggle 1. form element.
This is my current code:
angular:
$scope.formWhat = false;
$scope.formShow = function(item){
$scope.formWhat = !$scope.formWhat;
};
html:
<div ng-repeat="x in comments">
replay
<form id="<%x.id%>" ng-show="formWhat">
blbllblblbl
</form>
</div>
This code will open all forms, but i need just on which is clicked, any idea?
One of the helpful things here is that ng-repeat creates a child scope for each item repeated.
So you can use a local variable inside that child scope that controller knows nothing about. This won't close any of the others but that could be accomplished also. Criteria you gave wasn't very specific
<div ng-repeat="x in comments">
<a ng-click="showForm = !showForm">replay</a>
<form ng-show="showForm"></form>
</div>
I'm very new to angular and I was trying some things out.
I've created a controller that shows (toggles) a menu. In the menu there are a few li's with some directives. One of them has ng-click="erase()". When clicking it, I would like the element itself to be removed (deleted). It is possible to do that? In jQuery it was, I think: element.remove();
Here is my code:
<div ng-controller="DeathrayMenuController">
<button ng-click="toggleMenu()">Toggle Menu</button>
<ul ng-show="menuState">
<li ng-click="stun()">Stun</li>
<li ng-click="disintegrate()">Disintegrate</li>
<li ng-click="erase()">Erase from history</li>
</ul>
</div>
The ng-click="erase()" should remove the entire li from the ul.
And here is my code:
$scope.erase = function(){
console.log($scope);
};
Hope someone could land me a hand. Many thanks!
To remove elements, you can use the ng-if directive. This will remove the element when the expression is false.
Here's an example:
$scope.erase = function() {
$scope.erased = true;
}
<li ng-click="erase()" ng-if="!erased">Erase from history</li>
In Angular, your JavaScript shouldn't manipulate the DOM. Instead, your JavaScript manipulates the $scope, and the directives manipulate the DOM.