Angular2 Radio buttons and Checkbox binding - forms

I am currently using beta.17 within this web application i am building, as it had issues when trying to upgrade. But anyway thats not the issue.
I have a Model form, and I am trying to use Radio Buttons, and I know there was always issues with it until the fix on rc2.
But here is my section of the form using them:
<div *ngFor="let ctrl of markingForm.controls['design'].controls; let i = index;" [ngFormModel]="ctrl">
<accordion-group [heading]="ctrl.value.name" >
<div *ngFor="let design of studentAssign.assID[0].template[0].design; let j = index">
<label class="form-check-inline" *ngFor="let comment of design.comments">
<input name="input" class="form-check-input" type="radio" value="test" ngControl="comment">{{comment.short}}
</label>
</div>
</accordion-group>
</div>
I am trying to bind the value to 'comment' within this part of the ControlArray:
"design": [
{
"name": "Rubric Section Name",
"comment": null,
"mark": null,
"maxMark": 50
},
{
"name": "ttt",
"comment": null,
"mark": null,
"maxMark": 20
}
]
(the 'design' part is populated before hand and could be X amount big).
So realistically it should work right?
But i get this error:
ORIGINAL EXCEPTION: TypeError: Cannot read property 'value' of null
ORIGINAL STACKTRACE:
TypeError: Cannot read property 'value' of null
at RadioControlValueAccessor.onChange
Is there any way around this? Or is there a fix or do I need to upgrade to rc2?
Or can the radio buttons be easily replicated with checkboxes?

Related

SAPUI5 binding OData v4

I'm currently using OData v4 requests from my CAP app, and the problem is how to bind my Entity requested data in my Simple Form.
The user must input a Workspace code, and Search for its values.
Please, how do I bind and display my Workspace name and description values to my Simple Form fields to be displayed on screen?
Workspace CAP entity data:
{
"#odata.context": "$metadata#Workspace/$entity",
"name": "Projeto Compra de Material Escritorio",
"description": "",
"projectState": "Active",
"testProject": "false",
"version": "Original",
"baseLanguage": "pt"
}
in the onInit app function
let oModel = new sap.ui.model.odata.v4ODataModel({
groupId : "$auto",
synchronizationMode : "None",
serviceUrl : "/myCAP_URL/"
in my press event button
let oModel = this.getView().getModel();
let oContextBinding = oModel.bindContext(`/Workspace/${workspaceId}`);
oContextBinding.requestObject("name").then(function (sName) {
if (!sName) {
oContextBinding.getBoundContext().setProperty("name", "No name");
}
});
Finally, that`s my Simple Form fields (XML)
<Button id="button0" press="onPress" text="Search"/>
<f:SimpleForm editable="true" layout="ResponsiveGridLayout" id="form0">
<f:content>
<sap.ui.core:Title text="{description}" id="title2"/>
<Label text="Name" id="label0"/>
<Input width="30%" id="input0" value="{name}"/>
<Label text="Language" id="label1"/>
<Input width="30%" id="input2" value="{baseLanguage}"/>
</f:content>
</f:SimpleForm>
I've managed to bind and display data, based on this piece of code. I`ve just made some adjustments.
oContextBinding.requestObject("name").then(function(sName) {
if (!sName) {
oContextBinding.getBoundContext().setProperty("name", "No name");
}
});

AMP autocomplete how get id from autocomplete results and display only text in input

view screen I am using https://amp.dev/documentation/components/amp-autocomplete/ and I am able show in results id and name concated in one string, but I need show only name and store id in hidden input.
code screen
<amp-autocomplete filter="substring" filter-value="name" min-characters="2" src="/ajax/get_active_clinics.php" class="name_autocomplete">
<input type="text" placeholder="Numele clinicii" name="clinic_name" id="clinic_name"
{literal}on="change:AMP.setState({clinic_name_validation: true, form_message_validation:true})"{/literal}>
<span class="hide"
[class]="formResponse.clinic_name && !clinic_name_validation ? 'show input_validation_error' : 'hide'">Clinica este obligatorie</span>
<template type="amp-mustache" id="amp-template-custom">
{literal}
<div class="city-item" data-value="ID - {{id}}, {{name}}">
<div class="autocomplete-results-item-holder">
<div class="autocomplete-results-item-img">
<amp-img src="{{link}}" alt="{{name}}" width="40" height="40"></amp-img>
</div>
<div class="autocomplete-results-item-text">{{name}}</div>
</div>
</div>
{/literal}
</template>
</amp-autocomplete>
You can use the select event on amp-autocomplete to get the event.value which will return the value of the data-value attribute of the selected item.
https://amp.dev/documentation/components/amp-autocomplete/#events
You can then call the split() string method on the result.
You'll need to modify the data-value in your mustache template like so:
<div class="city-item" data-value="{{id}},{{name}}">
Then add the following code to your autocomplete, this will assign the split values to 2 temporary state properties.
<amp-autocomplete
...
on="select: AMP.setState({
clinicName: event.value.split(',')[0],
clinicId: event.value.split(',')[1]
})"
>
Once these values are in state you can then access them using bound values. Note the [value] attribute, this will update the inputs value when state changes. It's worth mentioning that the change in value won't trigger the change event listener on your input here as it's only triggered on user interaction.
<input
type="text"
placeholder="Numele clinicii"
name="clinic_name"
id="clinic_name"
[value]="clinicName"
on="change:AMP.setState({
clinic_name_validation: true,
form_message_validation:true
})"
/>
Last thing you'll need to do is add the hidden input for Clinic ID, again this will need to be bound to the temporary state property clinicId.
<input
type="hidden"
name="clinic_id"
[value]="clinicId"
>

Angular 2 - Handling multiple checkboxes checked state

I'm building a registration form, and have to handle multiple checkboxes generated through *ngFor structural directive.
Template:
<div class="form-group">
<label class="col-lg-3 control-label">Response Type</label>
<div class="col-lg-7">
<div class="checkbox" *ngFor="let type of client.responseTypes; let i = index">
<label>
<input type="checkbox" name="responseTypes" [(ngModel)]="client.responseTypes[i].checked" /> {{type.value}}
</label>
</div>
</div>
</div>
TS model object:
client.responseTypes = [
{ value: 'type1', checked: false},
{ value: 'type2', checked: true },
{ value: 'type3', checked: true }
];
The actual values behind the scene checked or unchecked are stored correctly. But, the checkboxes do not show the correct value.
If one of the three objects.checked == false, all checkboxes will show unchecked
Only if all three objects.checked == true, all three will be checked in the form.
I tried fiddling with [value]="client.responseTypes[i].checked" and [checked]="client.responseTypes[i].checked" on the input element, but to no success.
Any pointers in the right direction are massively appreciated.
Regards, Chris
the syntax is ok, well, you can do too
<input type="checkbox" name="responseTypes" [(ngModel)]="type.checked">
the problem is in other place (when you defined the client -I think you write some like this.client.responseTypes=...-), you can write
{{client |json }}
to check it
Alright after trying to wrap my head around why my local application wasn't showing the result I wanted, I started to copy and paste my form-group out of the <form></form> element it was in.
Ta-daa, it works now.
FYI: Placing *ngFor checkboxes inside a <form></form> element results in unwanted behaviour.
In angular every model bind with name , means you need to give unique name to each Form elements`
For Example:
<div class="form-group"><label class="col-lg-3 control-label">Response Type</label>
<div class="col-lg-7">
<div class="checkbox" *ngFor="let type of client.responseTypes; let i = index">
<label>
<input type="checkbox" name="type.id" [(ngModel)]="client.responseTypes[i].checked" /> {{type.value}}
</label>
</div>
</div>
</div>
Object :
client.responseTypes = [{id: '1', value: 'type1', checked: false},
{id: '2', value: 'type2', checked: true },
{id: '3', value: 'type3', checked: true }];
And now Check :) Thank you

About the $dirty property and getting only modified fields in a form

I have a form with few fields and I'm trying to get modified fields only.
Here is what I got so far (simplified version) :
<form name="formTicket">
<div class="item title">
<label for="category-assignation"><?php echo T::_("Assignation :")?></label>
<textarea type="text" name="assignation" cols="50" rows="4" id="category-assignation" data-ng-model="ticket.assignation"></textarea>
</div>
<div class="item title">
<input id="save" type="submit" value="Save" data-ng-click="saveTicketInfo()" />
</div>
</form>
In my controller.js, I have :
$scope.saveTicketInfo = function() {
console.info($scope.ticket);
console.info($scope.formTicket);
//Query to my service to save the data
Category.saveInfo.query({data: $scope.ticket});
};
Prior to AngularJs, I would save my fields in an array at the loading of my form and compare their values with the new values posted. I could still do this but I'm looking for an AngularJs approach.
I've been trying to use the $dirty property of each field and only send to my services those with "true" value but this behavior is not suitable for me : if the defaut value for my field is "test" and the user modify the input to "test2" and modify it back to "test" and post it, $dirty will be true (even if the value has not really changed).
Is there any convenient and optimal way to achieve what I want ?
Thank you for your time.

Meteor: how to accept user input in a set of form fields

New to Meteor. I have a form with several fields
<template name="addcityform">
<form name="addcity">
<input name="city" class="city" type="text">
<input name="population" class="population" type="text">
<input type="Submit" value="Add City">
</form>
</template>
I just want to insert the fields into the database, but I'm stumped on how to do it. Here's what I currently have after several attempts:
Template.addcityform.events({
'submit .addcity' : function(evt, template) {
Cities.insert({
city: template.find('input.city').value,
population: template.find('input.population').value
});
}
});
// this gives: Uncaught TypeError: Cannot read property 'value' of null
I saw some examples that use Session.set and document.getElementById, but that seems clumsy to me due to the potential for namespace conflicts. I'd like to do this the 'right way' so that it's extensible later, for example, I could put multiple instances of the form onto the page and they should be independent of each other. What is the 'right way' to do this?
You lack an event.preventDefault() in the "submit form" handler, or else the page will reload and ruin the single-page app experience of Meteor.
I would do something like :
<template name="addcityform">
<form>
<input name="city" class="city" type="text">
<input name="population" class="population" type="text">
<button type="submit">Add City</button>
</form>
</template>
Template.addcityform.events({
"submit form": function(event, template) {
event.preventDefault();
Cities.insert({
city: template.find(".city").value,
population: template.find(".population").value
});
}
});
What's cool about Meteor templates is that css selectors used within them are local to the current template, meaning that "submit form" will always refer to "submit event of the form element in enclosing template", given that you only have one form in the template.
The same applies to template instances .find method : it will return an element matching the css selector within the template or its sub-templates.
This allows you to have multiple instances of your addcityform that will be independent from each other.