How to implement ControlValueAccessor in Angular in a interdepend form - javascript

I have two dropdown fields that are separate components using ControlValueAccess. I want to change the data in the second field based on the selection of the first. For example, if field type has a value of honda then I'd like to change the data for the second field model to include an array of honda models. If the type has a selected field of toyota, I'd like to change the data in the model dropdown to include toyota models.
Here is the Stackblitz
https://stackblitz.com/edit/angular-ivy-7ry6vf?file=src/app/app.component.html
I've tried setting this.value to the appropriate array according to the value passed in, but I don't think this is the correct approach.
model.component.ts
writeValue(value: any): void {
if (value === 'honda') {
this.value = this.honda_models;
} else {
this.value = this.toyota_models;
}
// this.value = value;
}
Also, I'm having a hard time trying to get the value out of the app-type component
app.component.html
<form [formGroup]="form">
<app-type
formControlName="type"
(onChange)="onChange($event.target.value)"
></app-type>
<app-model formControlName="model"></app-model>
</form>

Related

Can't bind to dynamically added input in Bootstrap modal of Angular component

First of all, I don't see how the modal could have anything to do with this issue since its actually in this component's code, not a child. Still, this is in a modal, just in case.
I'm opting to not use FormArray since I need to keep track of my selections that may be added in a separate object, so I'm just creating unique IDs for the controls and adding them to the FormGroup. I can access the controls in the ts code, set values, get values, etc, but the form isn't binding and I can't figure out why not.
I can have an unknown number of items in this modal form, which will each have a selector (dropdown to select a property) and then the input to be able to modify some data. The input could be of different types, so it needs to be added and binded upon the choice from the selector.
<form [formGroup]="multiEditFormGroup" novalidate>
<div *ngFor="let item of multiEditSelections; let i = index">
<div>
<mdb-select [options]="availablePropsSelect"
placeholder="Choose property to edit"
class="colorful-select dropdown-main"
(selected)="multiEditSelectProp(item.selectorId, $event)"></mdb-select>
<label>Property to edit</label>
</div>
<div>
<div>
<input mdbActive
type="text"
class="form-control"
[formControlName]="item.controlId" />
</div>
</div>
</div>
</form>
Excepts of ts code:
public multiEditFormGroup = new FormGroup({});
onModalOpen():void {
const selectorId = this.utils.uuid();
this.multiEditFormGroup.addControl(selectorId, this.propSelector);
this.multiEditSelections.push({
selectorId: selectorId,
prop: '',
label: '',
type: '',
controlId: '' // not yet known since type hasn't been chosen
});
}
onSelect(selectorId: string, selectEvent: any): void {
let selection = this.multiEditSelections.find(selection => {
return selection.selectorId === selectorId;
});
const controlId = this.utils.uuid();
const prop = selectEvent.value;
this.multiEditFormGroup.get(selection.selectorId).setValue(prop);
this.multiEditFormGroup.markAsDirty();
this.multiEditFormGroup.markAsTouched();
const model = this.multiEditModel.find(model => {
return model.prop === prop;
});
this.multiEditFormGroup.addControl(controlId, this.testCtrl);
selection.controlId = controlId;
selection.prop = prop;
selection.label = model.label;
selection.type = model.type;
}
Logging to console shows that items are being added to the FormGroup, but the binding isn't happening to the DOM. For example, I can add a (keyup) event handler to my input and set the value in the form control which has already been created, and the FormGroup is updated. However, any input added in the front-end doesn't update the FG since it obviously isn't binding. Is this a timing issue or because the controlId is being updated later? I'm creating the FormControl before updating my array that is being iterated.
Oh and I get no errors in console on this.
I think you need to make this change:
[formControlName]="item.controlId"
needs to be:
formControlName="{{item.controlId}}"

Using JSON to permeate hidden fields

Using Laravel 5.2.* and plain JavaScript.
TL;DR
I need help in accessing JSON parameters to fill in the value attribute in some hidden fields
AND a way to take the "usefulInformation" value from the JSON and permeate a modal to provide users with information.
Not really interested in jQuery packages, because the project is already filled with over 20 packages.
I'm fairly new to both Laravel and JSON usage, so I've been running into a problem.
I have a page with a form that I have several parameters to fill out, but the most important ones are the hidden fields I set up to automatically fill up, because those are parameters that the user is, in a way, unaware of.
When the user submits the form, the parameters are inserted in the table "jobsCreated" that I have in my DB, the table is basically a way to keep track of every single little thing that the enterprise is doing (buying, selling, asking for new equipment, hiring, creating accounts to enter the system, etc.). The table is a mess in a way (the table has a bit over 20 columns and 11 of those are foreign keys)and it uses a composite key to generate the "createdJobID".
Most of the foreign keys in this table comes from another table called "jobsList". I've created a JSON file that has all the parameters and elements of this table. Like this:
jobs.json
{
"enterpriseID":2,
"sectionID":1,
"jobID":7,
"jobDescription":"Purchase - New Mouse for Deskjob",
"usefulInformation":"Please specify the value of the equipment",
"urgencyLevel":"normal",
"atendantID":0,
"isPublic":1,
"searchEqualFiles":0,
"formType":21
},
{
"enterpriseID":2,
"sectionID":1,
"jobID":8,
"jobDescription":"Purchase - New Laptop/Desktop to Deskjob",
"usefulInformation":"Inform the type of equipment and value",
"urgencyLevel":"normal",
"atendantID":0,
"isPublic":1,
"searchEqualFiles":0,
"formType":21
},
[ it goes on for another 260++ entries, following this model]
Another thing the system asks in the form, is an autocomplete-ish field that lists all of the jobs in the JSON. I've come up with a JavaScript code to permeate a datalist with several option fields, like this:
completeForm.js
// hidden inputs
var sectionId = document.getElementById('sectionId');
var jobId = document.getElementById('jobId');
var jobTypeId = document.getElementById('typeId');
var categoryId = document.getElementById('categoryId');
var selectionOption = document.getElementsByName('selectJob');
// input autocomplete e dataList
var input = document.getElementById('selectionAutocomplete');
var dataList = document.getElementById('jobsList');
var request = new XMLHttpRequest();
request.onreadystatechange = function(response)
{
if(request.readyState === 4)
{
if(request.status === 200)
{
// important bit, bolding it
var jsonOptions = JSON.parse(request.responseText);
for(var i = 0; i < jsonOptions.length; i++)
{
var option = document.createElement('option');
option.value = jsonOptions[i].jobDescription;
dataList.appendChild(option);
}
input.placeholder = "Type the name of a job";
}
else
{
input.placeholder = "No jobs found";
}
}
};
input.placeholder = "Loading jobs";
request.open('GET', '{{{ url('storage/app/jobs.json') }}}', true);
request.send();
Which works, the JSON is being parsed. If I do console.log(jsonOptions[i].jobDescription), for example, the right parameters are returned.
For my auto-complete field and hidden fields, I used the datalist element with the option element created in JavaScript.
// opening form, label and stuff
<input type="text" name="selectionAutocomplete" id="selectionAutocomplete" list="jobsList">
<datalist name="jobsList">
// options appended here
// elements look like this
// <option value="Purchase - New Mouse for Deskjob"></option>
</datalist>
<input type="hidden" name="sectionId" id="sectionId">
<input type="hidden" name="jobId" id="jobId">
<input type="hidden" name="typeId" id="typeId">
<input type="hidden" name="categoryId" id="categoryId">
In the hidden fields, I want to set up the value attribute to the same one that exists (if it exists) in the JSON.
So, for example, if I check the option "Purchase - New Mouse for Deskjob", I want to access the JSON position for this particular choice and permeate the value attribute in the hidden fields AND trigger a modal containing the "usefulInformation" string.
Any type of help is welcome. Thank you in advance.

Remove deselected checkbox value from Array using Angular

This is simple one but i still somehow couldn't get it to work.
I have default value checked, checkbox. So when edit, of course the default value is chosen, but later I want to remove the default value and choose another value. Here it is
array1=[] //empty
After I check a checkbox, it will inserted to this array
array1=["sun"]
If I select 3 values (array1["sun","stars","moon"])
but I deselect the first selection (the default selection), it will be still in the array. (array1["sun","stars","moon"]) but I the expected result is this:
array1["stars","moon"]
No more first selection. So how to remove deselected value from array using Angular/Javascript?
I have tried use splice, remove and set
Same thing developed and used in project :
Template side :
<label *ngFor="let hobby of hobbies" #checkbox class="mdl-checkbox mdl-js-checkbox">
<input type="checkbox" name="hobbies" [value]="hobby"
(change)="populateMyHobbies(hobby,$event.target.checked)" class="mdl-checkbox__input">
<span class="mdl-checkbox__label">{{hobby}}</span>
</label>
Component Side :
selectedHobbies = [];
populateMyHobbies(value , status:boolean)
{
if(this.selectedHobbies.indexOf(value) === -1 && status)
{
this.selectedHobbies.push(value);
}
else if(!status)
{
let index = this.selectedHobbies.indexOf(value);
this.selectedHobbies.splice(index, 1);
}
}
Here selectedHobbies will give you what you want.
Have to change just name as per your app.
i used it once in my project. change the code according to your need. logic is same.
html part
<input type="checkbox" value="{{category._id}}" (change)="pushpopcategory(category._id)" id="{{category._id}}">
component code
pushpopcategory(value) {
if ((<HTMLInputElement>document.getElementById(value)).checked) {
this.categoryAdd.push(value);
} else {
let indexx = this.categoryAdd.indexOf(value);
this.categoryAdd.splice(indexx, 1);
}
}

MVC4: Show validation error on the form or summary instead of an input?

I'm trying to leverage some form validation to do something it really wasn't designed to do. I have a table in my form and each row has a checkbox. I want to ensure that at least one of a specific type of checkbox is selected, if not I want to show a validation error. I am doing something similar with a text box with logic that looks like this:
function ValidateName() {
var $nameTextbox = $("#Name");
var $originalName = $("#OriginalName");
var nameText = $nameTextbox.val().toLowerCase();
var originalNameText = $originalName.val().toLowerCase();
//check to see if original name and group name match
if (nameText != originalNameText) {
//This isn't the same name we started with
if (uniqueNames.indexOf(nameText) > -1) {
//name isn't unique, throw validation error
var currentForm = $nameTextbox.closest("form");
//trigger validation
var errorArray = {};
errorArray["Name"] = 'Name must be unique';
currentForm.validate().showErrors(errorArray);
}
}
}
I've written something similar for the table and it works as long as I point the errorArray's index to the id of an input. However, I want to display the error somewhere more generic like the validation summary at the top of the form. How do I set up the error array to show on the form or the validation summary instead of a specific input? Is that even possible?
One way you could do this is you set a hidden input that is false when none are check and true if 1 or more are checked. You then listen to all the checkboxes by giving them all a class. I have an example shown below
http://jsfiddle.net/95acw2m9/
Html
<input type="hidden" id="IsCheckValue" name="IsCheckedValue" value="false"/>
<input type="checkbox" class="someCheckbox"/>
<input type="checkbox" class="someCheckbox"/>
<input type="checkbox" class="someCheckbox"/>
Jquery
$(document).ready(function(){
$(".someCheckbox").change(function(){
if($(".someCheckbox:checked ").length > 0){
$("#IsCheckValue").val("True")
}else{
$("#IsCheckValue").val("False")
}
})
})
Then pass that bool value in your model. In your controller method you can check the value of the bool. If the bool is false set the model to false like this
ModelState.AddModelError("Checkbox", "Must select one checkbox");
You can use the #Html.ValidationSummary() to display the error in your view.

how to set value in input field using angular js.?

I am making a view from json. I am able to that when I take json in a variable. But same thing when i read from file my view is not display. when comment the code which is working when I take json string in a variable.
Second issue
<div ng-switch-when="text" class="form-group">
<input type="text" value='login name' ng-model="outputs[input.name]"/>
<p ng-show="myfrm.input.$error.email && !myfrm.input.$pristine">Please enter a valid textl</p>
<p ng-show="myfrm.input.$error.required && !myfrm.input.$pristine">Please enter the text</p>
</div>
When I am using static value of input field like that(value='login name').it doesn't display that field value in input field.actually there is parameter value in my json I want to show value in input field (it there is any value it should display with filled value).
I take value like that
"value":value.value,
plunker: http://plnkr.co/edit/f3ZNtPbKeFkXnOOc3PNM?p=preview
actually why i am ready from file because there mat 1000 json object .i need to make 1000 form using one method
can I used this function
function changeData(data) {
var map = { NUMBER: "number", TEXT: "text", SWITCH: "select" };
// data is an object - use for .. in to enumerate
for (var key in data.input) {
var e = data.input[key]; // alias for efficient structure dereferencing
e.label = e.displayName;
e.title = e.displayDetail;
e.type = map[e.inputType];
delete e.displayName;
delete e.displayDetail;
delete e.inputType;
}
};
or I used this plugin
https://github.com/danhunsaker/angular-dynamic-forms

Categories