angular2 ngFor won't work - javascript

I'm trying to make some textboxes appear everytime a user clicks a button.
i'm doing this with ngFor.
For some reason, the ngFor won't iterate.
I've tried using slice to change the array reference, but still, the text boxes won't appear.
Any idea what i'm doing wrong??
Below are the HTML and component codes.
Thanks!!!
export class semesterComponent {
subjectsNames = [];
addSubject(subjectName: string) {
if (subjectName) {
this.subjectsNames.push(subjectName);
this.subjectsNames.slice();
console.log(subjectName);
console.log(this.subjectsNames);
}
};
<div class="semester-div">
<ul>
<li ngFor="let subject of subjectsNames">
<span>
<input #subjectName type="text" />
<input id = "subjectGrade" type = "number"/>
<input id = "subjectWeight" type = "number"/>
</span>
</li>
</ul>
<br>
<button (click)="addSubject(subjectName.value)">add</button>
<br>
</div>

You are missing the * in *ngFor
<li *ngFor="let subject of subjectsNames">

The way you have your controls written subjectName does not exist because the array is empty and therefore the *ngFor does not render it. Clicking the Add button results in a exception that the value doesn't exist on undefined where undefined is really subjectName.
Moving it outside of the *ngFor will make things work:
<input #subjectName type="text" />
<ul>
<li *ngFor="let subject of subjectsNames">
<span>
{{subject}}
<input id="subjectGrade" type="number"/>
<input id="subjectWeight" type="number"/>
</span>
</li>
</ul>
I suspect you also want to further bind the data as you iterate over the subject names but that's outside the scope of the question.
Here's a plunker: http://plnkr.co/edit/HVS0QkcLw6oaR4dVzt8p?p=preview

First, you are missing * in *ngFor.
Second put out
<input #subjectName type="text" />
from ngFor, should work.

Related

How to iterate through ul elements within a div and hide them individually on a submit?

In my node app using express I have a view function that creates a list of inactive companies, each company has two submit input types "Active" and "Delete". I would like to be able to hit submit and have that individual ul become hidden. However, I'm not quite sure how to iterate over individually. Every time I've tried I end up hiding all the elements. Here's my view function:
function inactiveFiltered(companyObject) {
return `
<ul class="companyinfo">
<li class="list-info">${companyObject.company_type}</li>
<li class="list-info">${companyObject.company_name}</li>
<li class="list-info">${companyObject.company_location}</li>
<li class="list-info">${companyObject.company_phone}</li>
<br>
<li class="list-buttons">
<form action="/activeList" method="POST" class="myform">
<input type="hidden" name="companyId" value="${companyObject.id}">
<input type="submit" value="Active">
</form>
<form action="/deletecompany" method="POST">
<input type="hidden" name="companyId" value="${companyObject.id}">
<input type="submit" value="Delete">
</form>
</li>
<br>
</ul>
`
}
function inactiveList(arrayOfCompanies){
const companyItems = arrayOfCompanies.map(inactiveFiltered).join('');
return `
<div class="list inactive-list">
${companyItems}
</div>
`
}
module.exports = inactiveList;
One function takes an array of companies and then creates an company object. Now here's the latest JQuery attempt, but like I said it hides all the ul elements:
$(document.body).submit(function() {
$('.companyinfo').each(function(i) {
$(this).hide();
})
})
I've been stuck on this for waaay too long and would love any help whatsoever. Thank you!
You are hiding all elements at the same time because the selector .companyinfo returns a list of all elements using the class companyinfo which are all companies in your case. That's why they get hidden all at the same time
One way to achieve your goal is to add ids to the ul elements to be able to address them for each company individually like so: <ul id="companyinfo_${companyObject.company_name}" class="companyinfo">.
Then add a method hideCompany() to replace the $(document.body).submit(function() part:
function hideCompany(companyname) {
$('#companyinfo_' + companyname).hide();
}
Finally, modify <input type="submit" value="Delete">to read <input type="submit" value="Delete" onclick="hideCompany('${companyObject.company_name}')">.

using template div id in an angular if statement

I have a modal with 3 lists that have unique ids:
<p class="accordion" ng-class"{active:accordion==2}" ng-click="accordion = 2">COPY from the PARCEL:</p>
<ul class="related_email_list accordion-content" ng-show="accordion==2">
<li ng-repeat="address in parcelAddressToStk">
<label for="selectAddress_parcel_{{address.AddressID}}">
<input type="checkbox" name="{{address.Alternate}}" class="parcelAddress" id="selectAddress_parcel_{{address.AddressID}}" value="{{address}}" ng-click="selectedAddresses(address);" ng-model="address.isSelected" ng-options="address.AddressID as address.pseudo for address in parcelAddressToStk" />
<span>
<b class="int-name">{{address.AddressType==='Mailing'?'Mailing Address:':(address.AddressType==='Street'?'Parcel Address:':(address.AddressType==='Mailing/Street'?'Mailing/Street Address:':'Home Quarter Address:'))}} </b>
<b>{{address.Alternate}}</b>
<b>{{address.StreetNumber?address.StreetNumber+" ":""}}{{address.StreetDirPre?address.StreetDirPre+" ":""}}{{address.StreetName?address.StreetName+" ":""}}{{address.StreetType?address.StreetType+" ":""}}{{address.StreetDirSuf?address.StreetDirSuf+" ":""}}{{address.UnitNumber!==""?"Unit " + address.UnitNumber:""}}</b>
<b>{{address.Municipality?address.Municipality+" ":""}}{{address.SubDivisionCode?address.SubDivisionCode+" ":""}}{{address.PCODE?address.PCODE+" ":""}}{{address.PostalZip?address.PostalZip+" ":""}}</b>
</span>
</label>
</li>
</ul>
I want to know if it's possible to use the selectAddress_parcel_{ID} in an if statement. I've tried
if ($scope["selectAddress_parcel_" + item.AddressID] == true) {
//do something
}
which comes back as undefined in the watch list. But if I hard-code selectAddress_parcel_56088 in watch I can see the correct object.
Is there an easier way to do this or am I concatenating my if statement incorrectly?

how to append input fields using push() function in angularjs?

I am creating add more field functionality in angularjs. I am using below code
Javascript
<script>
function FruitsController($scope){
var div = 'Apple';
$scope.fruits=[];
$scope.addFruit=function(){
$scope.fruits.push(div);
}
}
<script>
HTML
<ul><li ng-repeat="fruit in fruits">{{fruit}}</li></ul>
<button ng-click="addFruit()">Add</button>
Above code works successfully and appends 'Apple' string in body. But I want to append input type text field like string. So I am using below script that does not works.
<script>
function FruitsController($scope){
var div = '<input type="text">';
$scope.fruits=[];
$scope.addFruit=function(){
$scope.fruits.push(div);
}
}
<script>
I know above my code is totally wrong. Please give me some ideo that how to add input type in angularjs
You can render UI element in html. Your HTML looks like
<ul>
<li ng-repeat="fruit in fruits">
<input ng-model="fruit">
</li>
</ul>
<button ng-click="addFruit()">Add</button>
Your controller looks like
<script>
function FruitsController($scope){
var fruit = 'apple';
$scope.fruits=[];
$scope.addFruit=function(){
$scope.fruits.push(fruit);
}
}
<script>
Try this. For input text boxes you need to use ng-model attribute as it is two way data binding.
<ul>
<li ng-repeat="fruit in fruits">
<input type="text" ng-model="fruit">
</li>
</ul>
<button ng-click="addFruit()">Add</button>
<ul>
<li ng-repeat="fruit in fruits">
<input ng-model="fruit">
</li>
</ul>
<button ng-click="addFruit()">Add</button>
Keep your UI/HTML code in your HTML template, keep pure data structures in your controller. Through Angular's two-way data binding, ng-model will directly update your entries in $scope.fruits when your input changes.

How is replaceChild() supposed to work?

I am teaching myself javascript and don't understand the results I am getting from some example code. I have pruned the code for brevity.
The html:
<body>
<h1>firstChild and lastChild Property Lab</h1>
<hr />
<form>
<label>Enter some text to add or replace in the OL element:</label>
<br />
<input type="text" name="input" size="50" />
<br />
<input type="button" value="Insert at Top"
onclick="prepend(this.form)" />
<input type="button" value="Append to Bottom"
onclick="append(this.form)" />
<br />
<input type="button" value="Replace First Item"
onclick="replaceFirst(this.form)" />
<input type="button" value="Replace Last Item"
onclick="replaceLast(this.form)" />
</form>
<ol id="myList">
<li>Initial Item 1</li>
<li>Initial Item 2</li>
<li>Initial Item 3</li>
<li>Initial Item 4</li>
</ol>
</body>
The javascript:
// helper function for prepend() and append()
function makeNewLI(txt)
{
var newItem = document.createElement("LI");
newItem.innerHTML = txt;
return newItem;
}
function replaceFirst(form)
{
var newItem = makeNewLI(form.input.value)
var firstLI = document.getElementById('myList').firstChild.value;
document.getElementById('myList').replaceChild(newItem, firstLI);
}
I thought if I entered some text in the text box and clicked the Replace First Item button that the first item in the list would be replaced. However, the first time I do that it is prepended to the top of the list and the list now has 5 items. Then if I change the text in the text box and click the Replace First Item button again the first item in the list is changed.
I don't understand why this is happening. I expected the replacement would happen whenever I clicked the button. I am working with Firefox 4 on Ubuntu 10.04. Also, if I try to replace the last item in the list result is the same as I outlined above.
Thanks, Jim
There are 2 things wrong there. Firstly, you are selecting the value instead of the element with var firstLI = document.getElementById('myList').firstChild.value; so use var firstLI = document.getElementById('myList').firstChild; instead.
Secondly, believe it or not your firstChild is a TextNode with empty text with your current markup. Remove the empty space between <ol> and the first <li> so that its <ol><li>...., like here:
http://jsfiddle.net/niklasvh/5anyq/
Two problems:
You need to pass the node, not the value property (which doesn't even exist).
The first child is a text node, not the element (it's white space to be precise). You could either remove the white space or replace the call to firstChild with the more reliable .getElementsByTagName('li')[0].
Working jsFiddle
Some browsers support firstElementChild, which does what it says on the tin. For maximum efficiency, you could do this:
var list = document.getElementById('myList');
var firstLI = list.firstElementChild || list.getElementsByTagName('li')[0];

Getting value from input control using jQuery

I am using the teleriks treeview control (asp.net mvc extensions), where I may have up to three children nodes, like so (drumroll...... awesome diagram below):
it has its own formatting, looking a bit like this:
<%=
Html.Telerik().TreeView()
.Name("TreeView")
.BindTo(Model, mappings =>
{
mappings.For<Node1>(binding => binding
.ItemDataBound((item, Node1) =>
{
item.Text = Node1.Property1;
item.Value = Node1.ID.ToString();
})
.Children(Node1 => Node1.AssocProperty));
mappings.For<Node2>(binding => binding
.ItemDataBound((item, Node2) =>
{
item.Text = Node2.Property1;
item.Value = Node2.ID.ToString();
})
.Children(Node2 => Node2.AssocProperty));
mappings.For<Node3>(binding => binding
.ItemDataBound((item, Node3) =>
{
item.Text = Node3.Property1;
item.Value = Node3.ID.ToString();
}));
})
%>
which causes it to render like this. I find it unsual that when I set the value it is rendered in a hidden input ? But anyway:...
<li class="t-item">
<div class="t-mid">
<span class="t-icon t-plus"></span>
<span class="t-in">Node 1</span>
<input class="t-input" name="itemValue" type="hidden" value="6" /></div>
<ul class="t-group" style="display:none">
<li class="t-item t-last">
<div class="t-top t-bot">
<span class="t-icon t-plus"></span>
<span class="t-in">Node 1.1</span>
<input class="t-input" name="itemValue" type="hidden" value="207" />
</div>
<ul class="t-group" style="display:none">
<li class="t-item">
<div class="t-top">
<span class="t-in">Node 1.1.1</span>
<input class="t-input" name="itemValue" type="hidden" value="1452" />
</div>
</li>
<li class="t-item t-last">
<div class="t-bot">
<span class="t-in">Node 1.1.2</span>
<input class="t-input" name="itemValue" type="hidden" value="1453" />
</div>
</li>
</ul>
</li>
</ul>
What I am doing is updating a div after the user clicks on a certain node. But when the user clicks on a node, I want to send the ID not the Node text property. Which means I have to get it out of the value in these type lines <input class="t-input" name="itemValue" type="hidden" value="1453" />, but it can be nested differently each time, so the existing code I ahve doesn't ALWAYS work:
<script type="text/javascript">
function TreeView_onSelect(e) {
//`this` is the DOM element of the treeview
var treeview = $(this).data('tTreeView');
var nodeElement = e.item;
var id = e.item.children[0].children[2].value;
...
</script>
So based on that, what is a better way to get the appropriate id each time with javascript/jquery?
edit:
Sorry to clarify a few things
1) Yes, I am handling clicks to the lis of the tree & want to find the value of the nested hidden input field. As you can see, from the telerik code, setting item.Value = Node2.ID.ToString(); caused it to render in a hidden input field.
I am responding to clicks anywhere in the tree, therefore I cannot use my existing code, which relied on a set relationship (it would work for first nodes (Node 1) not for anything nested below)
What I want is, whenever there is something like this, representing a node, which is then clicked:
<li class="t-item t-last">
<div class="t-bot">
<span class="t-in">Node 1.1.2</span>
<input class="t-input" name="itemValue" type="hidden" value="1453" />
</div>
</li>
I want the ID value out of the input, in this case 1453.
Hope this now makes a lot more sense.
if possible would love to extend this to also store in a variable how nested the element that is clicked is, i.e. if Node 1.1.2 is clicked return 2, Node 1.1 return 1 and node 1 returns 0
It's a little unclear what you're asking, but based on your snippet of JavaScript, I'm guessing that you're handling clicks to the lis of the tree & want to find the value of the nested hidden field? If so, you want something like this:
function TreeView_onSelect(e) {
var id = $(e.item).find(".t-input:first").val();
}
Edit: In answer to your follow-up question, you should be able to get the tree depth with the following:
var depth = $(e.item).parents(".t-item").length;
In jQuery you can return any form element value using .val();
$(this).val(); // would return value of the 'this' element.
I'm not sure why you are using the same hidden input field name "itemValue", but if you can give a little more clarity about what you are asking I'm sure it's not too difficult.
$('.t-input').live('change',function(){
var ID_in_question=$(this).val();
});

Categories

Resources