I want to realize my selection with reactive Forms, i am new to this so here is my code:
I already tried to implement it with the documentation and the provided examples, but with no luck and destoying my single select radio button selection input. What do i need to implement in my .ts file and here in my html snippet to realize that?
Here is my working HTML Snippet:
<div *ngFor="let stream of myList">
<label>
{{ stream.sys }}
</label>
<p *ngFor="let type of stream.types">
<tr>
<input type="radio" name="nav"/>
{{ type.type.label }}
</tr>
</p>
</div>
I am looping over the outer list and the inner list with input Type radio. Everything works fine. Now i want to implement it to be Reactive Forms:
This is my desired Output for example:
Test
o Number 1
Test2
o Number 10
o Number 20
Test3
X Number 100
Value: Number 100 // or some id i have in my input data -> type.type.id
This navigation needs to be a select of one item and i want to show the form value unter my list as first step.
I tried something like this:
.html
<form [formGroup]="form">
<div *ngFor="let stream of myList">
<label>
{{ stream.sys }}
</label>
<p *ngFor="let type of stream.types">
<tr>
<input type="radio" name="name" formControlName="name" />
{{ type.type.label }}
</tr>
</p>
</div>
</form>
<p>
Value: {{ form.value | json}}
</p>
.ts
form: FormGroup;
constructor(private formBuilder: FormBuilder) {
this.form = formBuilder.group({
name: ['']
});
Your looping on myList. The formBuilder should contain an array of groups. And every single group should contain a 'name' control. 'value' should not be needed. And If you want to preset something you can set it in the formbuilder.
This is not related to the problem but I dont think the <tr> is incorrect in a <p>. Instead you could just add the loop on a div instead of a paragraph and then remove the tablerow
Related
Let's say I'm creating labels and form fields in a *ngFor loop like this:
app.component.ts
export class AppComponent {
items = ['aaa', 'bbbbbb', 'ccccccccc']
}
app.component.html
<div class='form'>
<ng-container *ngFor="let item of items">
<label>{{item|uppercase}}:</label>
<input [value]="item"/>
</ng-container>
</div>
(See it on StackBlitz: https://stackblitz.com/edit/angular-ptwq6t)
Is there a way to cleanly associate these "dynamic" labels and inputs with one another? If I do:
<label for="field" >{{item|uppercase}}:</label>
<input id="field" [value]="item"/>
Angular just repeats the for and id attributes verbatim and all labels point to the first input field.
Is there some way to use Angular's component identity, or am I stuck with something like generating a UUID myself, or otherwise guaranteeing uniqueness of the ID myself?
I can't nest the input inside the label because I have to reuse some already implemented CSS that doesn't expect that structure, but would still like the better usability that comes from having a proper label.
Given that the items are unique, you could surely do this:
<label [for]="item" >{{item|uppercase}}:</label>
<input [id]="item" [value]="item"/>
That way, each id and for would be unique and label would work as required.
Here is the demo.
If you anyway need to generate the unique IDs, take a look at shortid
you can try:
<div class='form'>
<ng-container *ngFor="let item of items">
<label for="{{item}} + 'field'" >{{item|uppercase}}:</label>
<input id="{{item}} + 'field'" [value]="item"/>
</ng-container>
</div>
or use the ngfor index if your items are not unique:
<div class='form'>
<ng-container *ngFor="let item of items; let i = index">
<label for="{{i}} + 'field'" >{{item|uppercase}}:</label>
<input id="{{i}} + 'field'" [value]="item"/>
</ng-container>
</div>
DEMO
I was trying to filter my columns in my django project template
Currently I am able to search in the table and display the rows that have that that value
But I would like to add a dropdown menu that would ask for a particular column value and then filter based on that value
currently my code is
views.py
def user_profile(request):
q = request.GET.get('q','')
custom = Customer.objects.all()
if q:
custom1=custom.filter(name__contains=q)
custom2=custom.filter(Product__contains=q)
custom3=custom.filter(L3__contains=q)
custom4=custom.filter(Server_Type__contains=q)
custom5=custom.filter(Version__contains=q)
custom6=custom.filter(Status__contains=q)
custom7=custom.filter(PM__contains=q)
custom8=custom.filter(CDM__contains=q)
custom = custom1 | custom2 | custom3 | custom4 | custom5 | custom6 |
custom7 | custom8
here name product l3 are my fields from my model that I would like to filter from
in my home.html
<input type="text" class="text_field" id="search" placeholder="Search for..." required>
<input type="button" class="button" onclick="go()" value="go" id="submit">
my js.js
function go(){
// alert("hellonikhar");
var q = document.getElementById("search").value;
window.open("/?q="+q,"_self");
}
I am storing the value entered in the textbox in var q and displaying the data but i would like to add a dropdown first which would choose the field and then q should filter based on only that column
For adding a dynamic dropdown send column names from the backend.
<select name="columns">
{% for column in columns %}
<option value="{{column.name}}">Column {{column.id}}: {{column.name}}</option>
{% endfor %}
</select>
Add a dropdown with id as the column name and filter the objects by using that column value.
Customer.objects.filter(**{columnName:columnValue})
Could you please try below query
Customer.objects.filter(Q(name__icontains=q)
|Q(Product__icontains=q)
|Q(L3__icontains=q)
|Q(Server_Type__icontains=q)
|Q(Version__icontains=q)
|Q(Status__icontains=q)
|Q(PM__icontains=q)
|Q(CDM__icontains=q)
)
I am trying to get the checked radio button and add the value to an Array. Currently, i cannot remove the previously checked radio buttons, so basically it keeps adding to the array every time i select a radio button.
item.component.ts
displaySelectedConditions(event) {
if(event.target.checked) {
this.selectedConditionsArr.push(event.target.value);
}
}
item.component.html
<ul class="dropdown-menu">
<li *ngFor="let item of filteredItems | funder "> //generates 4 items
<a><input type="radio" (change) = "displaySelectedConditions($event);"
name="funder" id="{{item}}" value="{{item}}">
<label for="{{item}}" >{{item}}</label></a>
</li>
</ul><!-- Dropdown Menu -->
I would suggest if you want to have the values neatly stored somewhere, then make use of a form. Simple template driven form works well here, then you would have all your values stored in an object, here's a sample:
<form #radioGroup="ngForm">
<div *ngFor="let str of strings">
<input type="radio" [value]="str" name="str" ngModel />{{str}}
</div>
<hr>
<div *ngFor="let num of numbers">
<input type="radio" [value]="num" name="num" ngModel />{{num}}
</div>
</form>
This would create an object like:
{
str: "value here",
num: "value here"
}
And if you declare the form like the following, you can easily access the object values:
#ViewChild('radioGroup') radioGroup: NgForm;
Somewhere in component:
console.log(this.radioGroup.value);
Plunker
I'm fairly new to angular, so hopefully this is a super simple question for someone to nail.
I have a form (cut down version below) that I want to be able to have a live preview being shown as the user fills in the form.
All was going well with standard fields, however I've hit a roadblock with <select> fields.
<div ng-app="jobcreate">
<div class="row fullWidth" ng-contoller="JobCtrl">
<div class="medium-6 columns">
<form method="POST" action="http://localhost:3030/job/create" accept-charset="UTF-8">
<label for="title">Enter a title</label>
<input placeholder="title" id="title" required="required" ng-model="job.title" name="title" type="text" />
<br />
<label for="title">Pick template</label>
<select ng-model="job.template" ng-options="template.Name for template in templates" name="template"></select>
</form>
</div>
<div class="medium-6 columns">
<div class='job-detail {{ job.template || "default" }}'>
<h2>{{ job.title || "Enter a title"}}</h2>
<h2>{{ job.template || "Pick a template"}}</h2>
<pre>Templates: {{templates | json}}</pre>
</div>
</div>
</div>
</div>
And here is the js:
angular.module('jobcreate', []).controller('JobCtrl', function($scope) {
$scope.templates = [
{ID:'default', name:'Default'},
{ID:'obnoxious', name:'Obnoxious'}
];
});
I have a jsfiddle here so you can see it in action: http://jsfiddle.net/2m8jm/4/
As you can see, entering something in the title field works as intended, but I'm struggling to get the contents of the $scope.colors to fill in the select field
In your fiddle : http://jsfiddle.net/2m8jm/4/, you have choosed templates as an data array for ng-options but there is not scope variable named templates in the controller JobCtrl. I have renamed $scope.colors to $scope.templates and modified the ng-options bit - ng-options="template.ID as template.name for template in templates".
Here is a working plunker : http://plnkr.co/edit/wsbxkjRqTEU2yfcHOV0D?p=preview
Update
Is there a way to not have the first empty value be in the select field?
Yes, Couple of ways.
1) Initialize job.template with some default value in your markup as :
<label for="title" ng-init="job.template='obnoxious'">Pick template</label>
<select ng-model="job.template" ng-options="template.ID as template.name for template in templates" name="template"></select>
2) Define controller as follows to set default value for job.template inside the controller :
.controller('JobCtrl', function($scope) {
// some other codes
$scope.job = {};
$scope.job.template = 'default';
});
I'm trying to render a validation summary on a page using AngularJS. Here's what I have so far:
<div ng-app>
<div ng-controller="ctrl">
<form name="userForm">
<fieldset>
<legend>User Info</legend>
<p><label>Name: <input type="text" required ng-maxlength="15" name="name" ng-model="name" /></label></p>
<p><label>Age: <input type="number" required name="age" ng-model="age" /></label></p>
<p><label>Favorite Color: <input type="text" required name="favColor" ng-model="favColor" /></label></p>
<p><input type="button" value="Submit" ng-click="submitForm()" /></p>
</fieldset>
</form>
<div id="validationSummary" ng-show="hasValidationErrors()">
<ul>
<li ng-repeat="error in validationErrors">{{ error }}</li>
</ul>
</div>
</div>
</div>
In my controller, I'm creating an array with all of the errors.
function ctrl($scope) {
$scope.hasValidationErrors = function () {
return $scope.validationErrors && $scope.validationErrors.length > 0;
};
$scope.submitForm = function() {
$scope.validationErrors = [];
for (var property in $scope.userForm) {
if ($scope.userForm.hasOwnProperty(property) && $scope.userForm[property].$invalid) {
$scope.validationErrors.push($scope.userForm[property].$name);
}
}
}
}
The thing I can't figure out is: how can I get more than just the name of each field that is invalid? I've noticed that there is also an $error property on each field. Outputting this instead of $name gives me the following:
{"required":true,"maxlength":false}
{"required":true,"number":false}
{"required":true}
So I can get the field name, and I can get an object that describes what is wrong with that particular field. How can I define an error message, so that if a field is required it will output "{name} is required"? It seems like this could be a data- attribute on the input element itself, although I don't know how I would access that attribute.
Of course, it's also possible that I'm making things entirely too difficult on myself. Is there a better way to approach this while staying in the "AngularJS" world?
Here's a link to the jsFiddle I've been working on.
A far easier and cleaner way is demonstrated here
Simply put (where form1 is your form name attribute):
<ul>
<li ng-repeat="(key, errors) in form1.$error track by $index"> <strong>{{ key }}</strong> errors
<ul>
<li ng-repeat="e in errors">{{ e.$name }} has an error: <strong>{{ key }}</strong>.</li>
</ul>
</li>
</ul>
A totally dynamic validation summary based on AngularJS 1.5.7 with ngMessages using field names that the user recognizes
A template with error messages:
<script type="text/ng-template" id="error-messages">
<span ng-message="required">This field is required.</span>
<span ng-message="email">Please enter a valid email.</span>
</script>
Display of the error summary (here for a form named "candidateForm"):
<div data-ng-if="candidateForm.$submitted && candidateForm.$invalid">
Please correct these fields and then try to send again:
<ul>
<li data-ng-repeat="field in candidateForm" data-ng-if="candidateForm[field.$name].$invalid">
<div>
{{ getValFieldName(field) }}
<span data-ng-messages="candidateForm[field.$name].$error" role="alert">
<span data-ng-messages-include="error-messages"></span>
</span>
</div>
</li>
</ul>
</div>
A helper function to get the name of the label associated with the input field (instead of displaying input field names or "internal ID codes" to users):
$scope.getValFieldName = function (field) {
return $("label[for=" + field.$name + "]").text(); // to get label associated with input field
// return $("#" + field.$name).attr("placeholder"); // to get placeholder of input field
};
You can reuse this set of standard error messages on multiple forms, ngMessages ensure only one error displayed per field, and looks like the fields are listed in the order they appear in the HTML.
Should probably be made into a directive instead of the jQuery-style helper function, and might even want to add a click-handler on each error message to scroll to the input field with the error. Maybe another will run with that idea?
Use below line to get values of every text box
var value = $scope.userForm[property].$name;
var vl =$('*[name="' + value + '"]').data('required-message')
$scope.validationErrors.push(vl);