How do I clear the FormArray in Angular Reactive Forms - angular-reactive-forms

I am doing resetting of form. It resets the whole form but except FormArray.
Creating the form and declaring formArray within it
createForm(){
this.invoiceForm = this.formBuilder.group({
'name': ['', Validators.required],
'gst': [''],
'currency': [''],
'addressLine1': ['', Validators.required],
'addressLine2': [''],
'city': ['', Validators.required],
'state': ['', Validators.required],
'country': ['', Validators.required],
'postalCode': ['', Validators.required],
'email': ['', [Validators.required, Validators.email]],
'invoiceparticulars': this.formBuilder.array([]),
'isGstshidden' : true
});
}
Trying to modify details of the form from the incoming data by resetting the data even though I called reset() function formArray retaining previous entries in it.
modifyInvoice(index){
this.invoiceForm.reset();
let modifyData = this.modifyInvoiceArray[index];
console.log(modifyData);
this.invoiceNumber = modifyData.invoiceNumber;
this.invoiceForm.patchValue({name: modifyData.address.Name});
this.invoiceForm.patchValue({email: modifyData.email});
this.invoiceForm.patchValue({gst: modifyData.GSTnumber});
this.invoiceForm.patchValue({addressLine1: modifyData.address.AddressLine1});
this.invoiceForm.patchValue({addressLine2: modifyData.address.AddressLine2});
this.invoiceForm.patchValue({city: modifyData.address.City});
this.invoiceForm.patchValue({country: modifyData.address.Country});
this.invoiceForm.patchValue({postalCode: modifyData.address.PostalCode});
this.invoiceForm.patchValue({state: modifyData.address.State});
console.log(modifyData['particulars']);
}

Angular 8
simply use clear() method on formArrays :
(this.invoiceForm.controls['invoiceparticulars']).clear();
OR :
let frmArray = this.invoiceForm.get('invoiceparticulars') as FormArray;
frmArray.clear();

Try to add this code
const control = <FormArray>this.invoiceForm.controls['invoiceparticulars'];
for(let i = control.length-1; i >= 0; i--) {
control.removeAt(i)
}

Related

How to assign (use) input name to Uppy uploader when we have multiple uppy uploader

I am trying to use Uppy to upload some images in my Laravel application. I need multiple uppy elements in one page that each one upload one specific image. For example Uppy1 for upload Nationality Card image and Uppy2 for upload Drive Licence image. I use below code for upload images.
<script>
const Dashboard = Uppy.Dashboard;
const XHRUpload = Uppy.XHRUpload;
var cls = '.kt_uppy';
var options = {
proudlyDisplayPoweredByUppy: false,
target: id,
inline: true,
resultName: 'uppyResult',
replaceTargetContent: true,
showProgressDetails: true,
note: null,
height: 170,
metaFields: [
{ id: 'name', name: 'Name', placeholder: 'file name' },
{ id: 'caption', name: 'Caption', placeholder: 'describe what the image is about' }
],
browserBackButtonClose: true,
}
var uppyDashboard = Uppy.Core({
autoProceed: true,
restrictions: {
maxFileSize: 1000000, // 1mb
maxNumberOfFiles: 1,
minNumberOfFiles: 1
}
});
uppyDashboard.use(Dashboard, options);
uppyDashboard.use(XHRUpload, {
endpoint: '{{ route('upload') }}',
})
Problems:
1 - Can we use and init multiple uppy elements just with write one code? (above code)
because number of persons that I need to get informations are Flexible. For ex: one family have 1 child and other family have 3 children and number of Nationality Card to upload is flexible
2 - How to assign different name attribute to each uppy element? like: <input type="file" name"name1"> and <input type="file" name"name2">
you can use Uppy id options
you set id options in Uppy instance
then, you can control each Uppy instance separately
So, there are two ways for setting id
const uppy = Uppy({id: 'new id'})
const uppy = Uppy()
uppy.setOptions({id: 'new id'})
so edit your code like below example
var uppyDashboard = Uppy.Core({
autoProceed: true,
restrictions: {
maxFileSize: 1000000, // 1mb
maxNumberOfFiles: 1,
minNumberOfFiles: 1
}
});
var uppyOneDashboard = Uppy.Core({
id: 'id 1',
autoProceed: true,
restrictions: {
maxFileSize: 1000000, // 1mb
maxNumberOfFiles: 1,
minNumberOfFiles: 1
}
});
var uppyTwoDashboard = Uppy.Core({
id: 'id 2',
autoProceed: true,
restrictions: {
maxFileSize: 1000000, // 1mb
maxNumberOfFiles: 1,
minNumberOfFiles: 1
}
});
then, you have two separate Uppy instances
good luck

JSON schema validation with perfect messages

I have divided the data entry in a REST call in 4 parts. Data can be sent to REST call via:-
headers
query params
path params
request body
So in order to validate the presence of any key in any of the above 4 parts I have created a schema in this format. So if in case I have to validate anything in query params I will add the key 'query' and then add the fields inside that, that needs to be validated
const schema = {
id: 'Users_login_post',
type: 'object',
additionalProperties: false,
properties: {
headers: {
type: 'object',
additionalProperties: false,
properties: {
Authorization: {
type: 'string',
minLength: 10,
description: 'Bearer token of the user.',
errorMessages: {
type: 'should be a string',
minLength: 'should be atleast of 23 length',
required: 'should have Authorization'
}
}
},
required: ['Authorization']
},
path: {
type: 'object',
additionalProperties: false,
properties: {
orgId: {
type: 'string',
minLength: 23,
maxLength: 36,
description: 'OrgId Id of the Organization.',
errorMessages: {
type: 'should be a string',
minLength: 'should be atleast of 23 length', // ---> B
maxLength: 'should not be more than 36 length',
required: 'should have OrgId'
}
}
},
required: ['orgId']
}
}
};
Now, in my express code, I created a request object so that I can test the validity of the JSON in this format.
router.get("/org/:orgId/abc", function(req, res){
var request = { //---> A
path: {
orgId : req.params.orgId
},
headers: {
Authorization : req.headers.Authorization
}
}
const Ajv = require('ajv');
const ajv = new Ajv({
allErrors: true,
});
let result = ajv.validate(schema, request);
console.log(ajv.errorsText());
});
And I validate the above request object (at A) against my schema using AjV.
The output what I get looks something like this:
data/headers should have required property 'Authorization', data/params/orgId should NOT be shorter than 23 characters
Now I have a list of concerns:
why the message is showing data word in the data/headers and data/params/orgId even when my variable name is request(at A)
Also why not my errormessages are used, like in case of orgId I mentioned: should be atleast of 23 length (at B) as a message, even then the message came should NOT be shorter than 23 characters.
How can I show request/headers instead of data/headers.
Also, the way I used to validate my path params, query params, header params, body param, is this the correct way, if it is not, then what can be the better way of doing the same?
Please shed some light.
Thanks in advance.
Use ajv-keywords
import Ajv from 'ajv';
import AjvKeywords from 'ajv-keywords';
// ajv-errors needed for errorMessage
import AjvErrors from 'ajv-errors';
const ajv = new Ajv.default({ allErrors: true });
AjvKeywords(ajv, "regexp");
AjvErrors(ajv);
// modification of regex by requiring Z https://www.regextester.com/97766
const ISO8601UTCRegex = /^(-?(?:[1-9][0-9]*)?[0-9]{4})-(1[0-2]|0[1-9])-(3[01]|0[1-9]|[12][0-9])T(2[0-3]|[01][0-9]):([0-5][0-9]):([0-5][0-9])(.[0-9]+)?Z$/;
const typeISO8601UTC = {
"type": "string",
"regexp": ISO8601UTCRegex.toString(),
"errorMessage": "must be string of format 1970-01-01T00:00:00Z. Got ${0}",
};
const schema = {
type: "object",
properties: {
foo: { type: "number", minimum: 0 },
timestamp: typeISO8601UTC,
},
required: ["foo", "timestamp"],
additionalProperties: false,
};
const validate = ajv.compile(schema);
const data = { foo: 1, timestamp: "2020-01-11T20:28:00" }
if (validate(data)) {
console.log(JSON.stringify(data, null, 2));
} else {
console.log(JSON.stringify(validate.errors, null, 2));
}
https://github.com/rofrol/ajv-regexp-errormessage-example
AJV cannot know the name of the variable you passed to the validate function.
However you should be able to work out from the errors array which paths have failed (and why) and construct your messages from there.
See https://ajv.js.org/#validation-errors
To use custom error messages in your schema, you need an AJV plugin: ajv-errors.
See https://github.com/epoberezkin/ajv-errors

Instafeed: skip retrieving video type posts from feed

I want to skip all video type posts from a feed that I'm gathering through the Instafeed JS plugin. Read from a few other posts that setting a filter would solve it but if I apply this (see below) I only get 2 images instead of 5. 1 of those 5 are a video type and the rest are image types. Not sure whats going on here?
var loadButton = document.getElementById('instafeed-loadmore');
var feed = new Instafeed({
get: 'user',
type: 'image',
limit: '5',
sortBy: 'most-recent',
resolution: 'standard_resolution',
userId: '',
accessToken: '',
template: '<div><img src="{{image}}" data-etc=""></div>',
filter: function(image) {
return image.type === 'image';
},
after: function() {
if (!this.hasNext()) {
loadButton.setAttribute('disabled', 'disabled');
}
},
});
loadButton.addEventListener('click', function() {
feed.next();
});
Maybe removing the resolution parameter should help. Also I dont think
type: 'image',
is a valid argument. I cant find it in the instafeed documentation as well.
TRy following
var feed = new Instafeed({
get: "user",
userId: "xxxx",
accessToken: "xxxx",
filter: function(image) {
if (image.type === "image") {
return false;
}
return true;
}
});
feed.run();

How do i add more that one Validator argument in Angular 2 form

I have tried adding multiple angular validator arguments [i.e Validators.minLength(8) and Validators.maxLength(12) ] to my form and i cant seem to get it to work...these arguments are attached to the (password and passwordc) instance in the code below. Any help please?
export class signupComponent {
signupform: FormGroup;
constructor(public fb: FormBuilder) {
this.signupform = this.fb.group({
firstname: ['', Validators.required],
lastname: ['', Validators.required],
account: this.fb.group({
email: ['', Validators.required],
**password: ['', Validators.minLength(8), Validators.maxLength(12), Validators.pattern('[A-Za-z]{5}')],
passwordc: ['', Validators.minLength(8), Validators.maxLength(12), Validators.pattern('[A-Za-z]{5}')],
}, { validator: passwordMatcher }),**
shortbio: ['', Validators.required]
});
}
}
To support multiple validators, you have to use the Validators.compose( [ ] ) method that accepts an array of validators. In your case:
password: ['', Validators.compose([Validators.minLength(8), Validators.maxLength(12), Validators.pattern('[A-Za-z]{5}')])]
password: ['', [Validators.minLength(8), Validators.maxLength(12), Validators.pattern('[A-Za-z]{5}')]]
This should do the job for you.

Properly chaining reducers when using combining them may not be appropriate

In my application, the state tree has this shape:
{
...otherReducers,
rooms: Map({
// room being the room's id
room: Map({
id: '',
name: '',
users: Map({
// user being the user's id
user: Map({
id: '',
name: '',
rank: ' '
})
})
})
})
}
In order to update a user's state, I've been writing my reducers as follows:
function roomsReducer(state = Map(), action) {
case USER_RENAME:
return selectRoom(state, action);
default:
return state;
}
function selectRoom(state, action) {
let room = state.get(action.payload.id);
return state.set(action.payload.id, roomReducer(room, action));
}
// and so on and so forth until I reach the user I want to update
Is there a way I an combine the users reducer with room, despite it having id and name properties? If not, is there a better way I could be managing my state to make reducing more manageable?
This is a problem with how you structure your state. Editing users would be much easier if it was normalized like so:
{
...otherReducers,
rooms: Map({
5: Map({
id: '5',
name: 'some name',
users: [1,4,52]
})
}),
users: Map({
1: Map({
id: '1',
name: 'Charles',
range: 'Master'
}),
4: Map({
id: '4',
name: 'Sally',
range: 'Master'
}),
52: Map({
id: '52',
name: 'Harry',
range: 'Novice'
})
})
}

Resources