How to use case statement with forEach in angular 6? - javascript

I want to select product in app.html from typesFurniture, in the uploadFiles() function to execute the product that I've selected, but i can't make it work. Help me please!
I've tryed with forEach and case statement but it didn't work. Don't know why...
i want to add images when i select one of my products through the dropdown list, my products are in array typesFurniture. But my problem here is i don't know to target selected product from dropdown list and then paste this code
const fileToUpload = this.files;
const filesIdx = _.range(fileToUpload.length);
_.each(filesIdx, (idx) => {
this.upload = new Upload(fileToUpload[idx]); this.uploadService.uploadFile(this.upload);
app.ts
export class DodavanjeSlikaComponent {
typesFurniture = ["Kuhinje", "Klizni ormari", "Ormari", "Radni stolovi", "Stolovi", "Cipelari", "TV Komode", "Police", "Paravani"];
files: FileList;
upload: Upload;
constructor(private uploadService: UploadService) { }
handleFiles(event) {
this.files = event.target.files;
}
uploadFiles() {
/* this have to include!
const fileToUpload = this.files;
const filesIdx = _.range(fileToUpload.length);
_.each(filesIdx, (idx) => {
this.upload = new Upload(fileToUpload[idx]);
this.uploadService.uploadFile(this.upload);
*/
// why this does not work, it won't execute the check that I've selected
this.typesFurniture.forEach(i => {
const fileToUpload = this.files;
const filesIdx = _.range(fileToUpload.length);
switch (i) {
case "Kuhinje":
_.each(filesIdx, (idx) => {
this.upload = new Upload(fileToUpload[idx]);
this.uploadService.uploadFile(this.upload);
});
break;
case "Klizni ormari":
_.each(filesIdx, (idx) => {
this.upload = new Upload(fileToUpload[idx]);
this.uploadService.uploadFile2(this.upload);
});
break;
}
})
}
}
app.html
<div id="dodavanje-proizvoda">
<div class="dodavanje-kocka">
<div class="vrsta">
<p>Izaberite vrstu proizvoda:</p>
<select>
<option *ngFor="let furniture of typesFurniture">{{furniture}}</option>
</select>
</div>
<div class="vrsta2">
<input type="file" (change)="handleFiles($event)" multiple>
</div>
<div class="vrsta3">
<input type="submit" value="Dodajte sliku" (click)="uploadFiles()">
</div>
</div>
</div>

Related

How to add filter in a Pug form?

This is an example of my database
I am making a website using nodejs, MongoDB, and pug. I have displayed this data in a pug form with the data in the select boxes. Like this but in pug using for loops and all the data-
<!DOCTYPE html>
<html>
<body>
<form>
<select name="Type">
<option value="Electronic">Electronic</option>
</select>
<select name="Brands">
<option value="Apple">Apple</option>
<option value="Dell">Dell</option>
<option value="Samsung">Samsung</option>
</select>
<select name="Products">
<option value="Macbook Pro">Macbook Pro</option>
<option value="Inspioren">Inspioren</option>
<option value="Galaxy S20">Galaxy S20</option>
</select>
</form>
</body>
</html>
What I want to do is, change the select box options based on what the user has selected in other select options.
For example:- If a user selects "Type: "Electronic", and "Brand: Apple",I want to display only Apple products as the options.
Or if a user selects "Type: "Electronic" it should automaticly display brands list in the select box for brands.
The data will be added from the database (it will not be hardcodded).
One possibility could be to modify your Pug view to include select tag id's and leave the downstream selects blank and then add a script at the end of your view to add event listeners and do some DOM manipulation using JQuery or just javascript after the view is loaded. The event handlers would then allow you to conditionally fill in your next select tag based on whatever you choose in the current tag.
Something along the lines of:
script.
document.addEventListener("DOMContentLoaded",
function(e) {
const typeSelect = document.getElementById('type')
typeSelect.onchange = function(e) {
const brandSelect = document.getElementById('brand')
if (typeSelect.options[typeSelect.selectedIndex].text === 'Apple') {
['MacBook Pro', 'MacBook Air', 'MacBook Mini'].forEach(function(product) {
let newOption = createElement('option')
newOption.textContent = product
brandSelect.appendChild(newOption
}
else if ( // etc... ) {}
else {
// functionality to clear out the downstream select tags.
}
}
const brandSelect = document.getElementById('brand')
brandSelect.onchange = // etc, etc....
})
Server side code, with some test data:
app.get("/avi", (req, res) => {
res.render("avi", { Types: [ "Electronic"], data:
[ { Type: "Electronic", Brand: "Apple", Products: [ "MacBook Pro", "MacBook Air", "Mac Mini"]},
{ Type: "Electronic", Brand: "Dell", Products: [ "Inspioren", "Latitude"]},
{ Type: "Electronic", Brand: "Samsung", Products: [ "Galaxy S20", "Galaxy S10"]}
]
});
});
You should include a Types list, otherwise your Pug script will have to go through the raw data to identify the number of unique Types.
avi.pug:
html
head
body
p Linked Dropdowns
form
p Type:
select#types(onchange="typeChanged()")
option(value="") Select Type
each item of Types
option(value=item)=item
p Brand:
select#brands(onchange="brandChanged()")
option(value="") Select Brand
p Product:
select#products()
option(value="") Select Product
script.
const data = JSON.parse(`!{JSON.stringify(data)}`);
const types = document.getElementById("types")
const brands = document.getElementById("brands")
const products = document.getElementById("products")
const typeChanged = () => {
clearBrands(); clearProducts();
if (types.selectedIndex!==0) {
const selectedType = types.options[types.selectedIndex].text;
data.forEach(d => {
if (d.Type===selectedType) {
const newBrand = document.createElement("option")
newBrand.value = newBrand.innerText = d.Brand;
brands.appendChild(newBrand);
}
});
}
}
const brandChanged = () => {
clearProducts();
if (brands.selectedIndex!==0) {
const selectedType = types.options[types.selectedIndex].text;
const selectedBrand = brands.options[brands.selectedIndex].text;
data.forEach(d => {
if (d.Type===selectedType && d.Brand===selectedBrand) {
d.Products.forEach(p => {
const newProd = document.createElement("option")
newProd.value = newProd.innerText = p;
products.appendChild(newProd);
});
}
})
}
}
const clearBrands = () => {
const item0 = brands.childNodes[0];
brands.textContent = "";
brands.appendChild(item0);
}
const clearProducts = () => {
const item0 = products.childNodes[0];
products.textContent = "";
products.appendChild(item0);
}
The data at the server is injected into the client side Javascript with:
const data = JSON.parse(`!{JSON.stringify(data)}`);
This method is not very robust. There will be problems if anywhere in the data there is a backtick ` character.
I am answering my own question here. What I did was add the onchange function on the Type select box. And created a script inside my file, with the following code-
function change() {
var Type_name = document.getElementById("type").value;
var Brand= document.getElementById('brands');
var Product = document.getElementById('products');
Brand.options.length = 0;
Product.options.length = 0;
var DefaultBrand = new Option("Brand", "Null");
var DefaultProduct = new Option ("Product", "Null");
Brand.add(DefaultBrand, undefined);
Product.add(DefaultProduct, undefined);
var product_master = !{JSON.stringify(product_names)};
for (const brands of product_master) {
if (brands.Type == Type_name){
const BrandOption = new Option(brands.Brand, brands.Brand);
Brand.add(BrandOption, undefined);
}
}
And another function similar to this to add products.
This worked for me. But if anyone wants to improve this code, I would appreciate the help.

Angular Table Delete Operation

In my app, I have a list where the user can add to and delete elements from it. My problem is, when I click an element (it can be in the middle, at the end etc.), it deletes the first element of the list. And when I refresh the page, I can see the previously 'deleted' elements. Like I haven't deleted anything. Here is my code. What's wrong with it and how should I fix it?
HTML:
<button mat-icon-button>
<mat-icon (click)="deleteWorkItem(row)">block</mat-icon>
</button>
TS:
deleteWorkItem(row: IProduct, index: number) {
let supplierProduct: ISupplierProduct = {
Supplier: {
SupplierId: this.SupplierId
},
Product: {
ProductId: row.ProductId
}
};
this.confirmDialogRef = this._dialog.open(FuseConfirmDialogComponent, {
disableClose: false
});
this.confirmDialogRef.componentInstance.confirmMessage = 'Ürünü silmek istiyor musunuz?';
this.confirmDialogRef.afterClosed().subscribe(result => {
if (result) {
this._service.update('Supplier/DeleteSupplierProduct', supplierProduct).subscribe(response => {
this._customNotificationService.Show('Ürün silindi', 'Tamam', 2);
});
let tempData = this.dataSource.data.slice(0);
tempData.splice(index, 1);
this.dataSource = new MatTableDataSource(tempData);
this.EditIndex = undefined;
this._products = this.dataSource.data;
this.ProductChange.emit(this._products);
}
});
}
You don't seem to pass index into deleteWorkItem method.
You need to declare a template variable within *ngFor as follows:
<div *ngFor="let row of data; let i = index">
...
<button mat-icon-button>
<mat-icon (click)="deleteWorkItem(row, i)">block</mat-icon>
</button>
</div>

Rendering a dynamic array of input

I'm trying to render a dynamic FormArray (When "+" is clicked it should add a new), but always when I put some file in the input box the Message ("Nenhum Arquivo Selecionado" which means "File Doesn't Exist") stays on the screen.
However, if I check the info on this.filterForm.get('Documents'), the row is filled correctly.
Does anyone have a sugestion to fix this error?
protocolo.component.ts
items: FormArray;
filterForm = new FormGroup({
IdProtocolo: new FormControl(),
Documentos: this.formBuilder.array([ this.createItem() ]
);
ngOnInit() {
this.items = this.filterForm.get('Documentos') as FormArray;
}
createItem(): FormGroup{
return this.formBuilder.group({
filename: '',
filetype: '',
value: ''
})
}
addItem(){
this.items.push(this.createItem());
}
removeItem(index){
if(this.items.length > 1) {
this.items.removeAt(index);
}
}
onFileChange(event: any, index: any) {
let reader = new FileReader();
if(event.target.files && event.target.files.length > 0) {
let file = event.target.files[0];
reader.readAsDataURL(file);
this.items.at(index).patchValue({
filename: file.name,
filetype: file.type,
value: (reader.result as string).split(',')[1]
})
}
}
protocolo.component.html
<div *ngFor="let item of filterForm.value.Documentos; let i = index;">
<div class="row" style="margin-bottom: 10px;">
<div class="col-md-4">
<input type="file" formControlName="Documentos" (change)="onFileChange($event, i)">
</div>
<div class="col-md-8">
<button class="btn btn-success-tce" (click)="addItem()">+</button>
<button class="btn btn-success-tce" (click)="removeItem(i)"style="margin-left: 5px">-</button>
</div>
</div>
[Updated] Possibly wrong implementation of formArray. I cannot see a formArrayName in your template. I would have implemented this like
In your template
<p> Dynamic File Form </p>
<form [formGroup]="someForm" (submit)="formSubmit()">
<div formArrayName="documents">
<div *ngFor="let item of files?.controls; let i = index;">
<input type="file" placeholder="Upload file" [formControlName]="i" (change)="onFileChange($event, i)"/>
</div>
</div>
<button type="submit"> Submit </button>
</form>
<button type="button" (click)="addFileControl()"> Add File </button>
In your component.
initForm() {
this.someForm = this.fb.group({
documents: this.fb.array([this.fileControl])
})
}
get files() {
return this.someForm.get('documents') as FormArray;
}
get fileControl() {
return this.fb.group({
file_item: [null]
})
}
addFileControl() {
this.files.push(this.fileControl);
}
formSubmit() {
console.log(this.someForm.value);
}
onFileChange(event, i) {
let reader = new FileReader();
if (event.target.files && event.target.files.length) {
const [file] = event.target.files;
reader.readAsDataURL(file);
reader.onload = () => {
this.files.controls[i].get('file_item').setValue(reader.result);
// need to run CD since file load runs outside of zone
this.cd.markForCheck();
};
}
}
Here is the stackblitz example. This will give you the output in base64 format but you can also get it in file format by modifying.
onFileChange(event, i) {
if (event.target.files && event.target.files.length) {
this.files.controls[i].get('file_item').setValue(event.target.files;);
}
}
Note:- It is just a rough code but does the job :).

precheck checkboxes depending on the response coming in json form in vuejs

Sorry for my English. I am trying to pre select those checkboxes whos values have been saved in the database. I did it using javascript in vuejs but those selected checkboxes values are not storing in array.
My code is like
role.component.js
getRoleRowData(data) {
this.roleaction = "edit";
this.addrolemodal = true;
console.log(data.role_id);
axios
.post(apiUrl.api_url + "getRolePermissionData", {
role_id: data.role_id
}).then(
result => {
this.permid = result.data;
var list = [];
result.data.forEach(function(value) {
list.push(value.perm_id);
});
var options = list;
for (var i = 0; i < options.length; i++) {
if (options[i]) document.querySelectorAll('input[value="' + options[i] + '"][type="checkbox"]')[0].checked = true;
}
},
error => {
console.error(error);
}
);
this.addrole = data;
},
And role.component.html
<div class="col-md-8">
<b-form-fieldset>
<div class="form" id="demo">
<h6>Permissions</h6>
<span v-for="perm_name_obj in listPermissionData">
<input type="checkbox" class="perm_id" v-bind:value="perm_name_obj.perm_id" name="perm_id" id="perm_name" v-model="checkedPerm_Id"> {{perm_name_obj.perm_name}}<br>
</span>
<span>Checked names: {{ checkedPerm_Id }}</span>
</div>
</b-form-fieldset>
</div>
And the Output
And the Ouput I got
In simple words I want to pre check checkboxes in vuejs of which values are stored in database.
See the following example, using simulation data
var app = new Vue({
el: '#app',
data () {
return {
listPermissionData: [],
checkedPerm_Id: []
}
},
created () {
setTimeout(_=>{
//Here simulates axois to request Permission data
this.listPermissionData = [
{perm_id:1,perm_name:'perm_name1'},
{perm_id:2,perm_name:'perm_name2'},
{perm_id:3,perm_name:'perm_name3'},
{perm_id:4,perm_name:'perm_name4'},
{perm_id:5,perm_name:'perm_name5'}
];
//Here simulates axois to request Selected Permissions (result.data)
var selected = [
{perm_id:2,perm_name:'perm_name2'},
{perm_id:5,perm_name:'perm_name5'}
]
this.checkedPerm_Id = selected.map(o=>o.perm_id)
},1000)
}
})
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<div id="app">
<div class="form">
<h6>Permissions</h6>
<span v-for="perm_name_obj in listPermissionData">
<input type="checkbox" class="perm_id" v-bind:value="perm_name_obj.perm_id" name="perm_id" id="perm_name" v-model="checkedPerm_Id"> {{perm_name_obj.perm_name}}<br>
</span>
<span>Checked names: {{ checkedPerm_Id }}</span>
</div>
</div>
I solved my problem, here is my code
role.component.js
getRoleRowData(data) {
this.roleaction = "edit";
this.addrolemodal = true;
console.log(data.role_id);
let tempthis = this;
axios
.post(apiUrl.api_url + "getRolePermissionData", {
role_id: data.role_id
}).then(
result => {
this.permid = result.data;
var list = [];
result.data.forEach(function(value) {
//by using tempthis variable we provided the current access to the checkedPerm_Id array which not accessible from out of the function which is getRoleRowData
tempthis.checkedPerm_Id.push(value.perm_id);
list.push(value.perm_id);
});
},
error => {
console.error(error);
}
);
this.addrole = data;
},

Ng-model did't show updated value until click somewhere on the page

All I want to do is to display the value of a ngModel, a variable defined in my controller. But the value didn't change to the correct value until I click somewhere else on the page or click the update button again. Although it does change to the correct value in the console.
My themeLayout.html file
<div class="theme-body" ng-controller="ThemeController as theme">
<select ng-model="theme.selectedTheme" ng-change="theme.getThemeDetails(theme.selectedTheme)">
<option ng-repeat="option in theme.themePacks">{{option.title}}</option>
</select>
<div class="form-group">
<label for="appLogo">App Logo</label>
<div>
<img ng-src="{{theme.currentThemeImageUrl}}" alt="Description" />
</div>
<input type="text" class="form-control" id="appLogo" ng-model="theme.currentThemeImageUrl">
</div>
</div>
And this is my theme controller
export default class ThemeController {
constructor($log, ApiService, $scope, $state, $window) {
'ngInject';
this.s3 = new this.AWS.S3();
this.selectedTheme = '';
this.currentThemeId = '';
this.currentS3ThemeOption = {};
this.currentS3ThemeOptionToUpload = {};
this.currentThemeImageUrl = '';
}
getThemeDetails(theme) {
this.$log.log(`get theme details function been called`, theme);
const obj = this;
for(let item of this.themePacks) {
if (theme === item.title) {
this.currentThemeId = item.themeId;
}
}
this.s3.getObject({
Bucket: `improd-image-pipeline`,
Key: `remoteUX/qa/${obj.currentThemeId}.json`,
}, (err, data) => {
if (err) {
obj.$log.log(err);
} else {
obj.currentS3ThemeOption = JSON.parse(data.Body);
obj.currentS3ThemeOptionToUpload = obj.currentS3ThemeOption;
for (const prop in obj.currentS3ThemeOption.colors) {
obj[prop] = obj.getColors(obj.currentS3ThemeOption.colors[prop]);
}
obj.currentThemeImageUrl = obj.currentS3ThemeOption.layout.titleImageUrl;
obj.$log.log(`We should have upadted theme opion now`, obj.currentS3ThemeOption, obj.currentThemeImageUrl);
}
});
this.$log.log(obj.currentS3ThemeOption, this.currentS3ThemeOption);
}
}
This is when I click the fox option in the selection, it read the data and stroe it into the currentSeThemeOption.
As you can see from the console, it also print of the value
What I am thingking is that might the 'this' and obj is causing the problem.
After I did add $scope.apply() function as he suggested, but it didn't solve the problem.
Update your model inside a scope.$apply() call:
getThemeDetails(theme) {
this.$log.log(`get theme details function been called`, theme);
const obj = this;
for(let item of this.themePacks) {
if (theme === item.title) {
this.currentThemeId = item.themeId;
}
}
this.s3.getObject({
Bucket: `improd-image-pipeline`,
Key: `remoteUX/qa/${obj.currentThemeId}.json`,
}, (err, data) =>
scope.$apply(() => {
if (err) {
obj.$log.log(err);
} else {
obj.currentS3ThemeOption = JSON.parse(data.Body);
obj.currentS3ThemeOptionToUpload = obj.currentS3ThemeOption;
for (const prop in obj.currentS3ThemeOption.colors) {
obj[prop] = obj.getColors(obj.currentS3ThemeOption.colors[prop]);
}
obj.currentThemeImageUrl = obj.currentS3ThemeOption.layout.titleImageUrl;
obj.$log.log(`We should have upadted theme opion now`, obj.currentS3ThemeOption, obj.currentThemeImageUrl);
}
})
);
this.$log.log(obj.currentS3ThemeOption, this.currentS3ThemeOption);
}
Once you have assigned a $scope object into the ng-model object. then you just put
$scope.$apply();
so that it will bind properly with UI elements.
It's the problem of digest cycle the digest cycle in triggered in only in four conditions
event (i.e your click),
http request,
change in input,
Timers with callbacks ($timeout etc.),

Categories

Resources