How to close a bootstrap modal manually (angular)? - angular-forms

I am building a sign up form inside a bootstrap modal.
After the submission (button press) the modal does not close.
I can't use the data-dismiss attribute because then the modal would be closed before the data is submitted for registration on the server side.
Was trying to solve it using ngbactivemodal but it seems something I did during the implementation of bootstrap-angular is not right.
Attached is:
The register component.ts-
import { Component, OnInit } from '#angular/core';
import { FormGroup, FormControl, Validators } from '#angular/forms';
import { matchOtherValidator } from '../match-other-validator';
import { HttpClient } from '#angular/common/http';
import { of } from 'rxjs';
import { map,take,switchMap} from 'rxjs/operators';
import { RegisterService } from '../register.service';
import {NgbActiveModal} from '#ng-bootstrap/ng-bootstrap'
const tzAsyncValidator = (http: HttpClient) => (c: FormControl) => {
console.log(c.parent);
if (!c || String(c.value).length === 0) {
console.log("!c|| String (c.value).length ===0")
return of(null);
}
return c.valueChanges.pipe(
take(1),
switchMap(_ =>
http.get('http://localhost:4000/userIds/' + String(c.value))
.pipe(
map((ids: any[]) => {
console.log(ids);
if (ids.length === 1) {
return { exists: true }
}
if (ids.length === 0) {
return null;
}
}))
))
}
#Component({
selector: 'app-register',
templateUrl: './register.component.html',
styleUrls: ['./register.component.css']
})
export class RegisterComponent implements OnInit {
public newUser;
public verification=false;
public newUser2;
public finalUser;
constructor(private http: HttpClient, public RS:RegisterService, private activeModal: NgbActiveModal) { }
ngOnInit() {
this.newUser = new FormGroup({
Tz: new FormControl('', [Validators.required, Validators.minLength(9), Validators.maxLength(9)], [tzAsyncValidator(this.http)]),
Email: new FormControl('', [Validators.required, Validators.email]),
PW: new FormControl('', [Validators.required, Validators.pattern('^(?=.*[0-9])(?=.*[a-zA-Z])([a-zA-Z0-9]+)$')]),
PWVerification: new FormControl('', [Validators.required, Validators.pattern('^(?=.*[0-9])(?=.*[a-zA-Z])([a-zA-Z0-9]+)$'), matchOtherValidator('PW')])
})
}
onSubmit(){
this.verification=true;
this.newUser2= new FormGroup({
City: new FormControl ('',Validators.required),
Street: new FormControl('',Validators.required),
FirstName: new FormControl('',Validators.required),
LastName: new FormControl('',Validators.required)
})
}
onSubmit2(){
this.finalUser=({...this.newUser.value,...this.newUser2.value});
this.RS.RegisterUser(this.finalUser)
.subscribe(()=>{
console.log(this.activeModal);
this.activeModal.close();
})
}
}
register component html-
<div class="modal fade" id="staticBackdrop" data-backdrop="static" tabindex="-1" role="dialog"
aria-labelledby="staticBackdropLabel" aria-hidden="true" data-toggle="modal" >
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="staticBackdropLabel">Sign Up!</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<form [formGroup]="newUser" (ngSubmit)='onSubmit()' *ngIf="verification!=true">
<label>ID</label>
<br>
<input type="text" placeholder="Please Enter Your ID" formControlName="Tz">
<br>
<label>Email</label>
<br>
<input type="email" placeholder="Please Enter Your Email" formControlName="Email">
<br>
<label>Password</label>
<br>
<input type="text" name="password" placeholder="Please Choose A Password" formControlName="PW" size="25">
<br>
<label>Resubmit Your Password</label>
<br>
<input type="text" name="confirmPassword" placeholder="Please Resubmit Your Password"
formControlName="PWVerification" validateEqual="password" size="30">
<br>
<input type="submit" class="btn btn-success" [disabled]="!newUser.valid">
<br>
<span *ngIf="newUser.get('Email').invalid &&!newUser.get('Email').pristine">Your email does not look
right</span>
<br>
<span *ngIf="newUser.get('Tz').errors?.maxlength ||newUser.get('Tz').errors?.minlength ">Your ID must contain
9 digits</span>
<br>
<span *ngIf="newUser.get('PW').invalid&&!newUser.get('PW').pristine">Password must include at least one letter
and one digit</span>
<br>
<span *ngIf="newUser.get('PWVerification').errors?.matchOther">Your submitted passwords don't match</span>
<br>
<span *ngIf="newUser.get('Tz').errors?.exists">This ID already exists</span>
</form>
<form [formGroup]="newUser2" *ngIf="verification!=false">
<label>City</label>
<br>
<input list="City" name="City" formControlName="City" placeholder="Choose City">
<datalist id="City">
<option value="Jerusalem">
<option value="Tel Aviv">
<option value="Haifa">
<option value="Rishon LeZion">
<option value="Petach Tikva">
<option value="Ashdod">
<option value="Netanya">
<option value="Be'er Sheva">
<option value="Holon">
<option value="Bnei Brak">
</datalist>
<br>
<label>Street</label>
<br>
<input type="text" placeholder="Please Input Street for Delivery" formControlName="Street">
<br>
<label>First Name</label>
<br>
<input type="text" placeholder="First Name here" formControlName="FirstName">
<br>
<label>Last Name</label>
<br>
<input type="text" placeholder="Last Name here" formControlName="LastName">
<br>
<input type="submit" class="btn btn-success" [disabled]="!newUser2.valid" (click)="onSubmit2()">
</form>
</div>
<div class="modal-footer">
</div>
</div>
</div>
app.module.ts-
import { BrowserModule } from '#angular/platform-browser';
import { NgModule } from '#angular/core';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { ReactiveFormsModule } from '#angular/forms';
import { HttpClientModule} from '#angular/common/http';
import { RegisterComponent } from './register/register.component';
import {NgbModule, NgbActiveModal} from '#ng-bootstrap/ng-bootstrap';
#NgModule({
declarations: [
AppComponent,
RegisterComponent,
],
imports: [
BrowserModule,
AppRoutingModule,
ReactiveFormsModule,
HttpClientModule,
NgbModule
],
providers: [NgbActiveModal],
bootstrap: [AppComponent]
})
export class AppModule { }
index.html-
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>YoavOnlineShop</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.min.css" integrity="sha384-Vkoo8x4CGsO3+Hhxv8T/Q5PaXtkKtu6ug5TOeNV6gBiFeWPGFN9MuhOf23Q9Ifjh" crossorigin="anonymous">
<link rel="icon" type="image/x-icon" href="favicon.ico">
</head>
<body>
<app-root></app-root>
<script src="https://code.jquery.com/jquery-3.4.1.slim.min.js" integrity="sha384-J6qa4849blE2+poT4WnyKhv5vZF5SrPo0iEjwBvKU7imGFAV0wwj1yYfoRSJoZ+n" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.min.js" integrity="sha384-wfSDF2E50Y2D1uUdj0O3uMBJnjuUD4Ih7YwaYd1iqfktj0Uod8GCExl3Og8ifwB6" crossorigin="anonymous"></script>
</body>
</html>
angular.json-
{
"$schema": "./node_modules/#angular/cli/lib/config/schema.json",
"version": 1,
"newProjectRoot": "projects",
"projects": {
"YoavOnlineShop": {
"projectType": "application",
"schematics": {},
"root": "",
"sourceRoot": "src",
"prefix": "app",
"architect": {
"build": {
"builder": "#angular-devkit/build-angular:browser",
"options": {
"outputPath": "dist/YoavOnlineShop",
"index": "src/index.html",
"main": "src/main.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.app.json",
"aot": false,
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"node_modules/bootstrap/dist/css/bootstrap.min.css"
],
"scripts": []
},
"configurations": {
"production": {
"fileReplacements": [
{
"replace": "src/environments/environment.ts",
"with": "src/environments/environment.prod.ts"
}
],
"optimization": true,
"outputHashing": "all",
"sourceMap": false,
"extractCss": true,
"namedChunks": false,
"aot": true,
"extractLicenses": true,
"vendorChunk": false,
"buildOptimizer": true,
"budgets": [
{
"type": "initial",
"maximumWarning": "2mb",
"maximumError": "5mb"
},
{
"type": "anyComponentStyle",
"maximumWarning": "6kb",
"maximumError": "10kb"
}
]
}
}
},
"serve": {
"builder": "#angular-devkit/build-angular:dev-server",
"options": {
"browserTarget": "YoavOnlineShop:build"
},
"configurations": {
"production": {
"browserTarget": "YoavOnlineShop:build:production"
}
}
},
"extract-i18n": {
"builder": "#angular-devkit/build-angular:extract-i18n",
"options": {
"browserTarget": "YoavOnlineShop:build"
}
},
"test": {
"builder": "#angular-devkit/build-angular:karma",
"options": {
"main": "src/test.ts",
"polyfills": "src/polyfills.ts",
"tsConfig": "tsconfig.spec.json",
"karmaConfig": "karma.conf.js",
"assets": [
"src/favicon.ico",
"src/assets"
],
"styles": [
"src/styles.css"
],
"scripts": []
}
},
"lint": {
"builder": "#angular-devkit/build-angular:tslint",
"options": {
"tsConfig": [
"tsconfig.app.json",
"tsconfig.spec.json",
"e2e/tsconfig.json"
],
"exclude": [
"**/node_modules/**"
]
}
},
"e2e": {
"builder": "#angular-devkit/build-angular:protractor",
"options": {
"protractorConfig": "e2e/protractor.conf.js",
"devServerTarget": "YoavOnlineShop:serve"
},
"configurations": {
"production": {
"devServerTarget": "YoavOnlineShop:serve:production"
}
}
}
}
}},
"defaultProject": "YoavOnlineShop"
}
package.json-
{
"name": "yoav-online-shop",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"test": "ng test",
"lint": "ng lint",
"e2e": "ng e2e"
},
"private": true,
"dependencies": {
"#angular/animations": "~8.2.9",
"#angular/common": "~8.2.9",
"#angular/compiler": "~8.2.9",
"#angular/core": "~8.2.9",
"#angular/forms": "~8.2.9",
"#angular/platform-browser": "~8.2.9",
"#angular/platform-browser-dynamic": "~8.2.9",
"#angular/router": "~8.2.9",
"#ng-bootstrap/ng-bootstrap": "^5.1.4",
"rxjs": "~6.4.0",
"tslib": "^1.10.0",
"zone.js": "~0.9.1"
},
"devDependencies": {
"#angular-devkit/build-angular": "~0.803.8",
"#angular/cli": "~8.3.8",
"#angular/compiler-cli": "~8.2.9",
"#angular/language-service": "~8.2.9",
"#types/node": "~8.9.4",
"#types/jasmine": "~3.3.8",
"#types/jasminewd2": "~2.0.3",
"codelyzer": "^5.0.0",
"jasmine-core": "~3.4.0",
"jasmine-spec-reporter": "~4.2.1",
"karma": "~4.1.0",
"karma-chrome-launcher": "~2.2.0",
"karma-coverage-istanbul-reporter": "~2.0.1",
"karma-jasmine": "~2.0.1",
"karma-jasmine-html-reporter": "^1.4.0",
"protractor": "~5.4.0",
"ts-node": "~7.0.0",
"tslint": "~5.15.0",
"typescript": "~3.5.3"
}
}

Providing ng-bootstrap into package.json:
"dependencies": {
... // dependencies over here
"#ng-bootstrap/ng-bootstrap": "xxx"
}
Then in angular.json:
"scripts": [
"node_modules/bootstrap/dist/js/bootstrap.min.js"
]
I do not import any js into my index.html
Finally in my component i use NgbModalRef instead. I' m posting the whole components so sorry about the boilerplate code.
import {Component, OnInit, ViewEncapsulation} from '#angular/core';
import {ParamsService} from '../../services/params.service';
import {NgbModal, NgbModalRef} from '#ng-bootstrap/ng-bootstrap';
import {NgxSpinnerComponent, NgxSpinnerService} from 'ngx-spinner';
import {FormBuilder, FormGroup, Validators, FormControl} from '#angular/forms';
import {UserService} from '../../services/user.service';
import {StudyDirection} from '../../model/direction.model';
import {forEach} from '#angular/router/src/utils/collection';
#Component({
selector: 'app-directions',
templateUrl: './directions.component.html',
styleUrls: ['./directions.component.scss'],
encapsulation: ViewEncapsulation.None
})
export class DirectionsComponent implements OnInit {
public directions: StudyDirection[];
public direction: StudyDirection;
public modalRef: NgbModalRef;
public form: FormGroup;
public tempDirection: StudyDirection;
constructor(private paramService: ParamsService,
private modalService: NgbModal,
private spinner: NgxSpinnerService,
private fb: FormBuilder,
private userService: UserService) {
}
ngOnInit() {
this.getDirections();
this.form = this.fb.group({
code: [null, Validators.required],
name: [null, Validators.required],
description: null,
parentDirectionid: null,
});
}
getDirections() {
this.paramService.getDirectionsList().subscribe(directions => {
this.directions = directions;
});
}
openAddModal(content) {
this.direction = new StudyDirection();
this.modalRef = this.modalService.open(content, {container: '.app'});
this.modalRef.result.then((result) => {
this.form.reset();
}, (reason) => {
this.form.reset();
});
}
deleteDirection(direction) {
this.spinner.show();
this.paramService.removeDirection(direction).subscribe(response => {
this.getDirections();
this.spinner.hide();
}, error => {
this.spinner.hide();
});
}
addDirection(directionid) {
this.paramService.addDirection(directionid).subscribe(response => {
this.getDirections();
this.modalRef.close();
}, error => {
console.log(error);
});
console.log(directionid);
}
closeModal() {
this.modalRef.close();
}
}
The .app is a class on top of my theme. So my modal opened with:
this.modalRef = this.modalService.open(content, {container: '.app'});
and then to close it:
this.modalRef.close();

Related

Angular 14: error NG8001: 'app-horizontal-bar-chart' is not a known element:

Can someone help me with this error? I have seen other possible solutions to solve this error but they have not worked.
Error: src/app/pages/home/home.component.html:5:9 - error NG8001: 'app-horizontal-bar-chart' is not a known element:
If 'app-horizontal-bar-chart' is an Angular component, then verify that it is part of this module.
If 'app-horizontal-bar-chart' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '#NgModule.schemas' of this component to suppress this message.
5
~~~~~~~~~~~~~~~~~~~~~~~~~~
src/app/pages/home/home.component.ts:5:16
5 templateUrl: './home.component.html',
~~~~~~~~~~~~~~~~~~~~~~~
Error occurs in the template of component HomeComponent.
package.json
{
"name": "goty",
"version": "0.0.0",
"scripts": {
"ng": "ng",
"start": "ng serve",
"build": "ng build",
"watch": "ng build --watch --configuration development",
"test": "ng test"
},
"private": true,
"dependencies": {
"#angular/animations": "^14.0.0",
"#angular/common": "^14.0.0",
"#angular/compiler": "^14.0.0",
"#angular/core": "^14.0.0",
"#angular/forms": "^14.0.0",
"#angular/platform-browser": "^14.0.0",
"#angular/platform-browser-dynamic": "^14.0.0",
"#angular/router": "^14.0.0",
"#cds/core": "^6.1.4",
"#clr/angular": "^13.8.2",
"#clr/icons": "^13.0.2",
"#clr/ui": "^13.8.2",
"#swimlane/ngx-charts": "^20.1.0",
"rxjs": "~7.5.0",
"tslib": "^2.3.0",
"zone.js": "~0.11.4"
},
"devDependencies": {
"#angular-devkit/build-angular": "^14.0.0",
"#angular/cli": "~14.0.0",
"#angular/compiler-cli": "^14.0.0",
"#types/jasmine": "~4.0.0",
"jasmine-core": "~4.1.0",
"karma": "~6.3.0",
"karma-chrome-launcher": "~3.1.0",
"karma-coverage": "~2.2.0",
"karma-jasmine": "~5.0.0",
"karma-jasmine-html-reporter": "~1.7.0",
"typescript": "~4.7.2"
}
}
project structure
app.module.ts
**import { NgModule} from '#angular/core';
import { BrowserModule } from '#angular/platform-browser';
import { AppRoutingModule } from './app-routing.module';
import { AppComponent } from './app.component';
import { ComponentsModule} from './components/components.module';
import { HomeComponent } from './pages/home/home.component';
import { VoteComponent } from './pages/vote/vote.component';
#NgModule({
declarations: [
AppComponent,
HomeComponent,
VoteComponent,
],
imports: [
BrowserModule,
AppRoutingModule,
ComponentsModule
],
providers: [],
bootstrap: [AppComponent],
})
export class AppModule { }**
home.component.ts
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.css']
})
export class HomeComponent implements OnInit {
constructor() { }
ngOnInit(): void {
}
}
home.component.html
<h2>Game of the year!!!</h2>
<hr>
<div class="row">
<div class="col">
<app-horizontal-bar-chart></app-horizontal-bar-chart>
</div>
</div>
app.component.html
<app-navbar></app-navbar>
<router-outlet></router-outlet>
components.module.ts
import { NgModule } from '#angular/core';
import { CommonModule } from '#angular/common';
import { RouterModule } from '#angular/router';
import { NgxChartsModule } from '#swimlane/ngx-charts';
import { BrowserAnimationsModule } from '#angular/platform-browser/animations';
import { NavbarComponent } from './navbar/navbar.component';
import { HorizontalBarChartComponent } from './horizontal-bar-chart/horizontal-bar-chart.component';
#NgModule({
declarations: [
NavbarComponent,
HorizontalBarChartComponent,
],
exports: [
NavbarComponent,
HorizontalBarChartComponent,
],
imports: [
CommonModule,
RouterModule,
NgxChartsModule,
BrowserAnimationsModule,
]
})
export class ComponentsModule { }
horizontal-bar-chart.component.ts
import { Component } from '#angular/core';
#Component({
selector: 'app-horizontal-bar-chart',
templateUrl: './horizontal-bar-chart.component.html',
styleUrls: ['./horizontal-bar-chart.component.css']
})
export class HorizontalBarChartComponent {
results: any[]=[
{
"name": "Game 1",
"value": 25
},
{
"name": "Game 2",
"value": 37
},
{
"name": "Game 3",
"value": 42
}
];
// options
showXAxis = true;
showYAxis = true;
gradient = true;
showLegend = true;
showXAxisLabel = true;
xAxisLabel = 'Games';
showYAxisLabel = true;
yAxisLabel = 'Votes';
colorScheme = 'nightLights';
}
horizontal-bar-chart.component.html
<div class="chart-container">
<ngx-charts-bar-horizontal [scheme]="colorScheme" [results]="results" [gradient]="gradient" [xAxis]="showXAxis" [yAxis]="showYAxis" [legend]="showLegend" [showXAxisLabel]="showXAxisLabel" [showYAxisLabel]="showYAxisLabel" [xAxisLabel]="xAxisLabel" [yAxisLabel]="yAxisLabel"
style="fill: grey">
</ngx-charts-bar-horizontal>
</div>

How to use "v-owl-carousel" with nuxt and vuetify?

I am working on a Nuxt app and using "Vuetify" as my frontend framework. In one of my pages I decided to use "v-owl-carousel" for making a carousel. The code of that page is below:
<template>
<v-container>
<v-row>
<v-col cols="12">
<client-only> <!-- important to add no-ssr-->
<carousel :autoplay="true" :number="6">
<v-card>
<img :src="require(`~/assets/imgs/books/07.webp`)">
</v-card>
<v-card>
<img :src="require(`~/assets/imgs/books/02.webp`)">
</v-card>
<v-card>
<img :src="require(`~/assets/imgs/books/03.webp`)">
</v-card>
<v-card>
<img :src="require(`~/assets/imgs/books/04.webp`)">
</v-card>
<v-card>
<img :src="require(`~/assets/imgs/books/05.webp`)">
</v-card>
<v-card>
<img :src="require(`~/assets/imgs/books/06.webp`)">
</v-card>
</carousel>
</client-only>
</v-col>
</v-row>
</v-container>
</template>
The problem here is that only 3 image of all images are shown in the carousel and when the carousel loops it shows nothing until it comes back to that 3 image. I find out that if I comment the "v-app" in my default.vue layout like below code, it works correctly:
<template>
<!--
<v-app dark lang="fa" dir="rtl">
<the-nanigation />
<v-main>
-->
<div id="mainContent">
<nuxt />
</div>
<!--
</v-main>
</v-app>
-->
</template>
But according to Vuetify documentation we must use v-app in our applications. So what is the solution to use v-owl-carousel in my app that uses Vuetify.
Alright, I did it for you here on this github repo: https://github.com/kissu/so-vuetify-awesome-swiper
It is mainly this
nuxt.config.js file
import colors from 'vuetify/es5/util/colors'
export default {
ssr: false,
target: 'static',
head: {
titleTemplate: '%s - so-vuetify-awesome-swiper',
title: 'so-vuetify-awesome-swiper',
htmlAttrs: {
lang: 'en',
},
meta: [
{ charset: 'utf-8' },
{ name: 'viewport', content: 'width=device-width, initial-scale=1' },
{ hid: 'description', name: 'description', content: '' },
{ name: 'format-detection', content: 'telephone=no' },
],
link: [{ rel: 'icon', type: 'image/x-icon', href: '/favicon.ico' }],
},
components: true,
buildModules: ['#nuxtjs/eslint-module', '#nuxtjs/vuetify'],
modules: ['#nuxtjs/axios'],
vuetify: {
customVariables: ['~/assets/variables.scss'],
theme: {
dark: true,
themes: {
dark: {
primary: colors.blue.darken2,
accent: colors.grey.darken3,
secondary: colors.amber.darken3,
info: colors.teal.lighten1,
warning: colors.amber.base,
error: colors.deepOrange.accent4,
success: colors.green.accent3,
},
},
},
},
}
This package.json
{
"name": "so-vuetify-awesome-swiper",
"version": "1.0.0",
"private": true,
"scripts": {
"dev": "nuxt",
"build": "nuxt build",
"start": "nuxt start",
"generate": "nuxt generate",
"lint:js": "eslint --ext \".js,.vue\" --ignore-path .gitignore .",
"lint": "yarn lint:js"
},
"dependencies": {
"#nuxtjs/axios": "^5.13.6",
"core-js": "^3.15.1",
"nuxt": "^2.15.7",
"swiper": "^6.8.4",
"vue-awesome-swiper": "^4.1.1",
"vuetify": "^2.5.5"
},
"devDependencies": {
"#babel/eslint-parser": "^7.14.7",
"#nuxtjs/eslint-config": "^6.0.1",
"#nuxtjs/eslint-module": "^3.0.2",
"#nuxtjs/vuetify": "^1.12.1",
"eslint": "^7.29.0",
"eslint-config-prettier": "^8.3.0",
"eslint-plugin-nuxt": "^2.0.0",
"eslint-plugin-prettier": "^3.4.1",
"eslint-plugin-vue": "^7.12.1",
"prettier": "^2.3.2"
}
}
And here is the .vue component that I've created
<template>
<div>
<p>Amazin swiper huh? 😄</p>
<swiper :options="swiperOptions" class="swiper">
<swiper-slide v-for="image in gallery" :key="image.id">
<img :src="image.src" />
</swiper-slide>
<div
v-show="prevSlideAvailable"
slot="button-prev"
#click="$refs.swiper.$swiper.slidePrev()"
></div>
<div
v-show="nextSlideAvailable"
slot="button-next"
#click="$refs.swiper.$swiper.slideNext()"
></div>
</swiper>
</div>
</template>
<script>
import { Swiper, SwiperSlide } from 'vue-awesome-swiper'
import 'swiper/swiper-bundle.css'
export default {
name: 'AwesomeSwiper',
components: {
Swiper,
SwiperSlide,
},
data() {
return {
gallery: [
{ id: 1, src: 'https://source.unsplash.com/random/500x500?sig=1' },
{ id: 2, src: 'https://source.unsplash.com/random/500x500?sig=2' },
{ id: 3, src: 'https://source.unsplash.com/random/500x500?sig=3' },
],
swiperOptions: {
slidesPerView: 1,
spaceBetween: 30,
lazy: false,
effect: 'fade',
pagination: {
el: '.swiper-pagination',
type: 'progressbar',
},
navigation: {
disabledClass: '.nice-meme',
nextEl: '.swiper-button-next',
prevEl: '.swiper-button-prev',
},
},
}
},
}
</script>
<style scoped>
.swiper {
width: 500px;
margin: 0 auto;
}
</style>
The result looks great so far

Why does vue.js not work inside html files?

I wanted to add Vue.js to my Spring Boot application. Even though everything seem to build fine, I cannot make vue component work.
Here is my simple component, MenuBar.vue:
<template>
<div>
Menu
</div>
</template>
<script>
export default {
name: "MenuBar"
}
</script>
And here is HTML which should be using it:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:th="https://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<title>Dashboard</title>
</head>
<body>
<div id="vueApp">
<menu-bar></menu-bar>
</div>
<form th:action="#{/logout}" method="post">
<div><input type="submit" value="Log out"/></div>
</form>
</body>
</html>
Configuration files index.js:
import Vue from "vue";
import App from './App.vue'
Vue.config.devtools = true;
new Vue({
el: '#app',
template: '<App/>',
components: {App}
});
new Vue({
el: '#vueApp'
})
components.js:
import Vue from 'vue';
import MenuBar from "./components/MenuBar";
Vue.component('menu-bar', MenuBar);
And webpack config file:
// webpack.config.js
const {VueLoaderPlugin} = require('vue-loader');
const path = require('path');
module.exports = {
mode: 'development',
module: {
rules: [
{
test: /\.vue$/,
loader: 'vue-loader'
},
{
test: /\.js$/,
loader: 'babel-loader'
},
{
test: /\.css$/,
use: [
'vue-style-loader',
'css-loader'
]
}
]
},
entry: {
main: path.resolve(__dirname, './src/index.js')
},
resolve: {
extensions: ['.vue', '.js'],
alias: {
'components': path.resolve(__dirname, './src/components/')
}
},
plugins: [
// make sure to include the plugin for the magic
new VueLoaderPlugin()
],
devServer: {
hot: false,
liveReload: true,
proxy: {
"*": {
target: 'http://localhost:8080',
ignorePath: false,
changeOrigin: false,
secure: false
}
},
port: 8081,
host: "0.0.0.0"
},
output: {
publicPath: '/dist/',
path: path.resolve(__dirname, './src/main/resources/static/dist')
}
}
When I build npm and run application page contains element <menu-bar></menu-bar> but does not load its content. What could be an issue here?
The problem is that you add the component inside of <div id="vueApp"> at:
<div id="vueApp">
<menu-bar></menu-bar>
</div>
In this case, your app renders inside of this <div id="vueApp"> tag. Everything you write inside of this tag at your html file, will be overwritten.
You have another file named App.vue. You should add your MenuBar.vue component to this main component and it should show.
EDIT: Easiest attempt to get your component to work
This ist the main.js:
import { createApp } from 'vue'
import App from './App.vue'
// Create app
const app = createApp(App);
// Import component
import MenuBar from "./components/MenuBar";
// Use MenuBar
app.component('MenuBar', MenuBar);
// Mount app
app.mount('#app')
This is the App.vue:
<template>
<div>
<MenuBar></MenuBar>
Body
</div>
</template>
<script>
export default {
name: 'App',
}
</script>
This is the MenuBar.vue:
<template>
<div>
Menu
</div>
</template>
<script>
export default {
name: "MenuBar"
}
</script>
As we have a slight different approach I will also give you the package.json, so you can just hit npm install and it should implement all the (few) packages includet in this app:
{
"name": "q68966956",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"core-js": "^3.6.5",
"vue": "^3.0.0"
},
"devDependencies": {
"#vue/cli-plugin-babel": "~4.5.0",
"#vue/cli-plugin-eslint": "~4.5.0",
"#vue/cli-service": "~4.5.0",
"#vue/compiler-sfc": "^3.0.0",
"babel-eslint": "^10.1.0",
"eslint": "^6.7.2",
"eslint-plugin-vue": "^7.0.0"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/vue3-essential",
"eslint:recommended"
],
"parserOptions": {
"parser": "babel-eslint"
},
"rules": {}
},
"browserslist": [
"> 1%",
"last 2 versions",
"not dead"
]
}
It looks like you are in a early stage with your project, so maybe you can start with a stable base from that code. Let me know, if it helped you.

what is this configuration error with Vue.js eslint

I am newer on vueJs. I try this basic code in my vue to modify datas of a component in a vue:
<template>
<div>
<h1> {{ message }}
<h2> Hello {{ firstname }} {{ lastname }} de {{ from }} ! </h2>
<label> Firstname : <input type="text" v-model="person.firstname" /> </label>
<label> Lastname : <input type="text" v-model="person.lastname" /> </label>
<label> Message : <input type="text" v-model="message" /> </label>
</div>
</template>
<script>
export default {
data () {
person: {
firstname: 'John',
lastname: 'Doe'
},
message: 'Welcome!'
}
}
</script>
I get this error:
Failed to compile.
./src/components/Hello.vue?vue&type=script&lang=js& (./node_modules/cache-loader/dist/cjs.js??ref--12-0!./node_modules/babel-loader/lib!./node_modules/cache-loader/dist/cjs.js??ref--0-0!./node_modules/vue-loader/lib??vue-loader-options!./src/components/Hello.vue?vue&type=script&lang=js&)
Module build failed (from ./node_modules/babel-loader/lib/index.js):
SyntaxError: C:\Users\1900780\Documents\Afpa\Ressources\PHP\vueJs1\myproject\src\components\Hello.vue: Unexpected token, expected ";" (16:16)
14 | person: {
15 | firstname: 'John',
> 16 | lastname: 'Doe'
| ^
17 | },
18 | message: 'Welcome!'
19 | }
at Object.raise (C:\Users\...\vueJs1\myproject\node_modules\#babel\parser\lib\index.js:7013:17)
at Object.unexpected (C:\Users\...\vueJs1\myproject\node_modules\#babel\parser\lib\index.js:8384:16)
at Object.semicolon (C:\Users\...\vueJs1\myproject\node_modules\#babel\parser\lib\index.js:8366:40)
at Object.parseExpressionStatement (C:\Users\...\vueJs1\myproject\node_modules\#babel\parser\lib\index.js:11193:10)
at Object.parseStatementContent (C:\Users\...\vueJs1\myproject\node_modules\#babel\parser\lib\index.js:10792:19)
at Object.parseStatement (C:\Users\...\vueJs1\myproject\node_modules\#babel\parser\lib\index.js:10658:17)
at Object.parseLabeledStatement (C:\Users\...\vueJs1\myproject\node_modules\#babel\parser\lib\index.js:11185:22)
at Object.parseStatementContent (C:\Users\...\vueJs1\myproject\node_modules\#babel\parser\lib\index.js:10790:19)
at Object.parseStatement (C:\Users\...\vueJs1\myproject\node_modules\#babel\parser\lib\index.js:10658:17)
at Object.parseBlockOrModuleBlockBody (C:\Users\...\vueJs1\myproject\node_modules\#babel\parser\lib\index.js:11234:25)
at Object.parseBlockBody (C:\Users\...\vueJs1\myproject\node_modules\#babel\parser\lib\index.js:11221:10)
at Object.parseBlock (C:\Users\...\vueJs1\myproject\node_modules\#babel\parser\lib\index.js:11205:10)
at Object.parseStatementContent (C:\Users\...\vueJs1\myproject\node_modules\#babel\parser\lib\index.js:10734:21)
at Object.parseStatement (C:\Users\...\vueJs1\myproject\node_modules\#babel\parser\lib\index.js:10658:17)
at Object.parseLabeledStatement (C:\Users\...\vueJs1\myproject\node_modules\#babel\parser\lib\index.js:11185:22)
at Object.parseStatementContent (C:\Users\...\vueJs1\myproject\node_modules\#babel\parser\lib\index.js:10790:19)
I use #vue/cli 4.1.2 and webpack.
My package.json:
{
"name": "myproject",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"core-js": "^3.4.4",
"vue": "^2.6.10"
},
"devDependencies": {
"#vue/cli-plugin-babel": "^4.1.0",
"#vue/cli-plugin-eslint": "^4.1.0",
"#vue/cli-service": "^4.1.0",
"babel-eslint": "^10.0.3",
"eslint": "^5.16.0",
"eslint-plugin-vue": "^5.0.0",
"vue-template-compiler": "^2.6.10"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"rules": {},
"parserOptions": {
"parser": "babel-eslint",
"ecmaVersion": 6
}
},
"browserslist": [
"> 1%",
"last 2 versions"
]
}
My code seems to be correct. I don't understand this error. Is there a config to do with babel parser and where is the config file ?
I added an eccmaversion in the package.json file configuration, but it does not seems to work. Any help would be appreciated.
Houps! i just forgot the return statement:
export default {
data () {
return {
person: {
firstname: 'John',
lastname: 'Doe'
},
message: 'Welcome!'
}
}
}

Why is lodash not working when I import it in Vue.js

I created a fresh new install of vue.js using "vue create todo --default" command. After that I installed lodash too with this command "npm i --save lodash". I can see it in my package.json on the "dependencies" object. The problem is that when I import it on my main.js and use the lodash functions, it is showing the error "_ is not defined". So I tried importing it inside the App.vue. The error "_ is not defined" was removed but it is not working.
Here are the code inside the App.vue, main.js, and package.json
main.js
import Vue from 'vue'
import App from './App.vue'
import "bootstrap/dist/css/bootstrap.min.css";
import "jquery/dist/jquery";
import "bootstrap/dist/js/bootstrap.min";
import _ from "lodash";
Vue.prototype._ = _;
Vue.config.productionTip = false
new Vue({
render: h => h(App),
}).$mount('#app')
App.vue
<template>
<div id="app">
<h4 class="bg-primary text-white text-center p-2">
{{name}}'s' To Do List
</h4>
<div class="container-fluid p-4">
<div class="row">
<div class="col font-weight-bold">Task</div>
<div class="col-2 font-weight-bold">Done</div>
</div>
<div class="row" v-for="t in completedtask" v-bind:key="t.action">
<div class="col">{{t.action}}</div>
<div class="col-2">
<input type="checkbox" v-model="t.done" class="form-check-input">
{{t.done}}
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data(){
return{
name: "Welly",
tasks: [{
action: "Buy Flowers",
done: false
},
{
action: "Get Shoes",
done: false
},
{
action: "Collect Tickets",
done: true
},
{
action: "Call Joe",
done: false
}
]
};
},
computed: {
hidecompletedtask(){
return _.map(this.tasks,(val)=>{
return !val.done;
});
}
}
}
</script>
<style>
</style>
package.json
{
"name": "todo",
"version": "0.1.0",
"private": true,
"scripts": {
"serve": "vue-cli-service serve",
"build": "vue-cli-service build",
"lint": "vue-cli-service lint"
},
"dependencies": {
"bootstrap": "^4.4.1",
"core-js": "^3.4.4",
"jquery": "^3.4.1",
"lodash": "^4.17.15",
"popper.js": "^1.16.1",
"vue": "^2.6.10"
},
"devDependencies": {
"#vue/cli-plugin-babel": "^4.1.0",
"#vue/cli-plugin-eslint": "^4.1.0",
"#vue/cli-service": "^4.1.0",
"babel-eslint": "^10.0.3",
"eslint": "^5.16.0",
"eslint-plugin-vue": "^5.0.0",
"vue-template-compiler": "^2.6.10"
},
"eslintConfig": {
"root": true,
"env": {
"node": true
},
"extends": [
"plugin:vue/essential",
"eslint:recommended"
],
"rules": {},
"parserOptions": {
"parser": "babel-eslint"
}
},
"browserslist": [
"> 1%",
"last 2 versions"
]
}
You'll still need to access the prototype via the this context, like this._.map().
computed: {
hidecompletedtask() {
return this._.map(this.tasks, (val) => {
return !val.done;
});
}
}
Reference: Adding Instance Properties.
Alternatively, you could extend the global window object. Put the following line in your main.js (or some booting file).
window._ = require('lodash');
Somewhere else where you need the library:
computed: {
hidecompletedtask() {
// The underscore (_) character now refers to the `window._ object`
// so you can drop the `this`.
return _.map(this.tasks, (val) => {
return !val.done;
});
}
}
You can also use vue-lodash package -- Follow these steps:
npm install --save vue-lodash
in main.js -- import VueLodash from 'vue-lodash'
in main.js after import -- Vue.use(VueLodash)
Usage:
Vue._.random(20);
this._.random(20);
-------- OR ------------
In your main.js add this line of code:
window._ = require('lodash');
That way it will work without Vue or this:
Just do -- _.map()
You can import lodash in your main.js file by javascript window object like this:
window._ = require('lodash');
Then use it anywhere in your projet like this:
var original = [
{ label: 'private', value: 'private#johndoe.com' },
{ label: 'work', value: 'work#johndoe.com' }
];
var update = [
{ label: 'private', value: 'me#johndoe.com' },
{ label: 'school', value: 'schol#johndoe.com' }
];
var result = _.unionBy(update, original);
var sortedresult = _map(_.sortBy(result, 'label'));
console.log(sortedresult);
I just use lodash unionBy and sortBy method for example.