How to correctly implement Tooltip in Angular 9 with Ng-Bootstrap 6 - ng-bootstrap

Trying to implement Tooltip in Angular 9 app with Ng-Bootstrap. I imported NgbModule in app.module, but no tooltips wouldn't display at all. app.module code:
import { NgbModule } from '#ng-bootstrap/ng-bootstrap';
#NgModule({
declarations: [
AppComponent
],
imports: [
CommonModule,
NgbModule,
SharedComponentsModule,
AppRoutingModule
],
providers: [
],
bootstrap: [AppComponent]
})
export class AppModule {
constructor(){}
}
I got Tooltip to work, but I had to import NgbModule in the component's parent module (SharedComponentsModule) and import NgbTooltip in the component itself (in addition to importing NgbModule in app.module) - didn't think these steps were necessary.
SharedComponentsModule code:
import { NgModule } from '#angular/core';
import { NgbModule } from '#ng-bootstrap/ng-bootstrap';
import { SharedComponentsRoutingModule } from './shared-components-routing.module';
import { searchComponent } from './search/search.component';
#NgModule({
declarations: [
searchComponent
],
imports: [
CommonModule,
NgbModule,
SharedComponentsRoutingModule
],
exports: [
]
})
export class SharedComponentsModule { }
searchComponents code:
import { Component, OnInit } from '#angular/core';
import { NgbTooltip } from '#ng-bootstrap/ng-bootstrap';
searchComponents.html code:
<button type="button" class="btn btn-outline-secondary mr-2" placement="left" ngbTooltip="Tooltip on left">Tooltip on left</button>
index.html code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>Search App</title>
<base href="/">
<meta name="viewport" content="width=device-width, initial-scale=1 shrink-to-fit=yes">
<link rel="icon" type="image/x-icon" href="favicon.ico">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.3.1/css/bootstrap.min.css" integrity="sha384-ggOyR0iXCbMQv3Xipma34MD+dH/1fQ784/j6cY/iJTQUOhcWr7x9JvoRxT2MZw1T" crossorigin="anonymous">
<link href="https://cdn.jsdelivr.net/gh/coliff/bootstrap-rfs/bootstrap-rfs.css" rel="stylesheet">
</head>
<body>
<app-root></app-root>
<script src="https://kit.fontawesome.com/************.js" crossorigin="anonymous"></script>
<script type="text/javascript" src="https://maps.googleapis.com/maps/api/js?libraries=places&key=*********************************"></script>
</body>
</html>
Question - is it necessary to import NgbModule in the parent module (in addition to app.module) of the component in which NgbModule is being used and import NgbTooltip (or any other Ng-Bootstrap component for that matter) in the component where the Ng-Bootstrap component is being used for it to work? Ng-Bootstrap documentation doesn't suggest doing this, but it's the only way I'm able to make it work. So any clues on what I might be doing incorrectly or any other settings I should tweak to avoid the unnecessary importing?

No, it is not necessary to import NgbModule to have the tooltips working.
As it is mentionned in the documentation :
Instead of importing the whole library with NgbModule, you could only
import modules with components you need, ex. pagination and alert.
The resulting bundle will be smaller in this case.
Your problem is that you try to import NgbTooltip, and you should import the module NgbTooltipModule instead :
import { NgbTooltipModule } from "#ng-bootstrap/ng-bootstrap";
#NgModule({
imports: [NgbTooltipModule],
})
That's it, everything should work now.

Related

Append 'build' in url laravel 9 vite after vite build command

Laravel 9
Using vite
Vue 3, Vue-router
Run command vite build and turn off vite server, all links in browser url get '/build/'
In code
<router-link to="/index">Index</router-link>
<router-link to="/">Main</router-link>
<router-view></router-view>
In browser
Vite config
import { defineConfig } from 'vite';
import laravel from 'laravel-vite-plugin';
import vue from '#vitejs/plugin-vue'
export default defineConfig({
plugins: [
vue(),
laravel({
input: ['resources/css/app.css', 'resources/js/app.js'],
refresh: true,
}),
],
});
Blade
<!DOCTYPE html>
<html lang="{{ str_replace('_', '-', app()->getLocale()) }}">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Laravel</title>
<!-- Fonts -->
<link href="https://fonts.bunny.net/css2?family=Nunito:wght#400;600;700&display=swap" rel="stylesheet">
#vite(['resources/css/app.css', 'resources/js/app.js'])
<!-- Styles -->
<style>
/*! normalize.css v8.0.1 | MIT License | github.com/necolas/normalize.css */html{line-height:1.15;-webkit-text-size-adjust:100%}body{margin:0}a{background-color:transparent}[hidden]{display:none}html{font-family:system-ui,-apple-system,BlinkMacSystemFont,Segoe UI,Roboto,Helvetica Neue,Arial,Noto Sans,sans-serif,Apple Color Emoji,Segoe UI Emoji,Segoe UI Symbol,Noto Color Emoji;line-height:1.5}*,:after,:before{box-sizing:border-box;border:0 solid #e2e8f0}a{color:inherit;text-decoration:inherit}svg,video{display:block;vertical-align:middle}video{max-width:100%;height:auto}.bg-white{--bg-opacity:1;background-color:#fff;background-color:rgba(255,255,255,var(--bg-opacity))}.bg-gray-100{--bg-opacity:1;background-color:#f7fafc;background-color:rgba(247,250,252,var(--bg-opacity))}.border-gray-200{--border-opacity:1;border-color:#edf2f7;border-color:rgba(237,242,247,var(--border-opacity))}.border-t{border-top-width:1px}.flex{display:flex}.grid{display:grid}.hidden{display:none}.items-center{align-items:center}.justify-center{justify-content:center}.font-semibold{font-weight:600}.h-5{height:1.25rem}.h-8{height:2rem}.h-16{height:4rem}.text-sm{font-size:.875rem}.text-lg{font-size:1.125rem}.leading-7{line-height:1.75rem}.mx-auto{margin-left:auto;margin-right:auto}.ml-1{margin-left:.25rem}.mt-2{margin-top:.5rem}.mr-2{margin-right:.5rem}.ml-2{margin-left:.5rem}.mt-4{margin-top:1rem}.ml-4{margin-left:1rem}.mt-8{margin-top:2rem}.ml-12{margin-left:3rem}.-mt-px{margin-top:-1px}.max-w-6xl{max-width:72rem}.min-h-screen{min-height:100vh}.overflow-hidden{overflow:hidden}.p-6{padding:1.5rem}.py-4{padding-top:1rem;padding-bottom:1rem}.px-6{padding-left:1.5rem;padding-right:1.5rem}.pt-8{padding-top:2rem}.fixed{position:fixed}.relative{position:relative}.top-0{top:0}.right-0{right:0}.shadow{box-shadow:0 1px 3px 0 rgba(0,0,0,.1),0 1px 2px 0 rgba(0,0,0,.06)}.text-center{text-align:center}.text-gray-200{--text-opacity:1;color:#edf2f7;color:rgba(237,242,247,var(--text-opacity))}.text-gray-300{--text-opacity:1;color:#e2e8f0;color:rgba(226,232,240,var(--text-opacity))}.text-gray-400{--text-opacity:1;color:#cbd5e0;color:rgba(203,213,224,var(--text-opacity))}.text-gray-500{--text-opacity:1;color:#a0aec0;color:rgba(160,174,192,var(--text-opacity))}.text-gray-600{--text-opacity:1;color:#718096;color:rgba(113,128,150,var(--text-opacity))}.text-gray-700{--text-opacity:1;color:#4a5568;color:rgba(74,85,104,var(--text-opacity))}.text-gray-900{--text-opacity:1;color:#1a202c;color:rgba(26,32,44,var(--text-opacity))}.underline{text-decoration:underline}.antialiased{-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale}.w-5{width:1.25rem}.w-8{width:2rem}.w-auto{width:auto}.grid-cols-1{grid-template-columns:repeat(1,minmax(0,1fr))}#media (min-width:640px){.sm\:rounded-lg{border-radius:.5rem}.sm\:block{display:block}.sm\:items-center{align-items:center}.sm\:justify-start{justify-content:flex-start}.sm\:justify-between{justify-content:space-between}.sm\:h-20{height:5rem}.sm\:ml-0{margin-left:0}.sm\:px-6{padding-left:1.5rem;padding-right:1.5rem}.sm\:pt-0{padding-top:0}.sm\:text-left{text-align:left}.sm\:text-right{text-align:right}}#media (min-width:768px){.md\:border-t-0{border-top-width:0}.md\:border-l{border-left-width:1px}.md\:grid-cols-2{grid-template-columns:repeat(2,minmax(0,1fr))}}#media (min-width:1024px){.lg\:px-8{padding-left:2rem;padding-right:2rem}}#media (prefers-color-scheme:dark){.dark\:bg-gray-800{--bg-opacity:1;background-color:#2d3748;background-color:rgba(45,55,72,var(--bg-opacity))}.dark\:bg-gray-900{--bg-opacity:1;background-color:#1a202c;background-color:rgba(26,32,44,var(--bg-opacity))}.dark\:border-gray-700{--border-opacity:1;border-color:#4a5568;border-color:rgba(74,85,104,var(--border-opacity))}.dark\:text-white{--text-opacity:1;color:#fff;color:rgba(255,255,255,var(--text-opacity))}.dark\:text-gray-400{--text-opacity:1;color:#cbd5e0;color:rgba(203,213,224,var(--text-opacity))}.dark\:text-gray-500{--tw-text-opacity:1;color:#6b7280;color:rgba(107,114,128,var(--tw-text-opacity))}}
</style>
<style>
body {
font-family: 'Nunito', sans-serif;
}
</style>
</head>
<body>
<div id="app">
</div>
</body>
</html>
app.js
import './bootstrap';
import {createApp} from 'vue'
import App from './App.vue'
import router from './router'
const app = createApp(App)
app.use(router)
app.mount("#app")
So i want to get in browser like this
http://localhost:8000/
http://localhost:8000/index
Without "build"
When i user working server vite with php artisan serve, all work fine, but when i want to prepare data for deploing, so do vite build, and turn off vite server, so append this work in url, but i dont want this word there.
For me working when i remove import.meta.env.BASE_URL from
Befor
const router = createRouter({
history: createWebHistory(**import.meta.env.BASE_URL**),
routes
});
After
const router = createRouter({
history: createWebHistory(),
routes
});
Please remove import.meta.env.BASE_URL parameter from createWebHistory() function in /resources/js/router/index.js.
Like this.
const router = createRouter({
history: createWebHistory(),
routes
});

Tailwind classes not getting applied for Astro Layouts

I am using Astro Tailwind integration, and I am trying to add some tailwind classes to MainLayout.astro which resides in layouts directory as follows
<!DOCTYPE html>
<html lang="en">
<head>
...
</head>
<body>
<main class="mx-20 mb-20 md:mb-28 xl:container xl:mx-auto">
<slot />
</main>
</body>
</html>
But styles are not getting applied to the <main> tag (according to browser dev tools inspection), but styles to the rest of the pages are getting applied.
What I have tried?
Restarting the dev server
Edit:
tailwind.config.cjs look like below
/** #type {import('tailwindcss').Config} */
module.exports = {
content: ["./src/**/*.{astro,html,js,jsx,md,mdx,svelte,ts,tsx,vue}"],
...
};
Edit 2:
astro.config.mjs
import { defineConfig } from "astro/config";
import react from "#astrojs/react";
import image from "#astrojs/image";
import tailwind from "#astrojs/tailwind";
// https://astro.build/config
export default defineConfig({
integrations: [
react(),
tailwind(),
image({
serviceEntryPoint: "#astrojs/image/sharp",
}),
],
});

How do I use PrimeVue in CustomElements?

I have a Vue 3 custom Element in which I want to use PrimeVue & PrimeFlex etc.
So I first create a Component, use the .ce.vue extension for the sfc mode and use the combination of defineCustomElement and customElements.define to compile it to a web component. Finally I use it in the index.html to see if it works in the Browser.
It works to some extent but not completely. For example, I am unsure about how to translate app.use(PrimeVue) for my case.
//customElement.ce.vue
<template>
<div>Test</div>
<AutoComplete field="name" />
</template>
<script lang="ts">
import { defineComponent } from "vue";
import AutoComplete from "primevue/autocomplete";
export default defineComponent({
name: "customElement",
props: {
msg: String,
},
components: { AutoComplete },
setup: () => {
console.log(JSON.stringify(theme));
return { PrimeVue };
},
styles: [],
});
</script>
<style scoped lang="scss"></style>
//main.ts
import { createApp, defineCustomElement } from "vue";
import App from "./App.vue";
//PrimeVue
import PrimeVue from "primevue/config";
import "/node_modules/primeflex/primeflex.css";
import "primevue/resources/primevue.min.css";
import "primevue/resources/themes/saga-blue/theme.css";
//CustomElement
import customElement from "#/components/customElement.ce.vue";
const customElementWC = defineCustomElement(customElement);
customElements.define("custom-element", customElementWC);
//Setup VueApplication for testing/reference, this works as expected.
const app = createApp(App);
app.use(PrimeVue);
app.mount("#app");
//index.html (for testing)
<!DOCTYPE html>
<html lang="">
<head>
<meta charset="utf-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
<link rel="icon" href="<%= BASE_URL %>favicon.ico" />
<title><%= htmlWebpackPlugin.options.title %></title>
</head>
<body>
<noscript>
<strong
>We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work
properly without JavaScript enabled. Please enable it to
continue.</strong
>
</noscript>
<div id="app"></div> //test app
<custom-element /> //the custom Web Component
<!-- built files will be auto injected -->
</body>
</html>
So I can see that the PrimeVue-Autocomplete is being shown, but the styles are not working.
So the question is:
How can I use all of PrimeVue in a custom Component?
Or in other words: How do I setup a Vue 3 CustomElement with PrimeVue?
So I have found a workaround (not a proper solution).
The way to make most of it work is to import the styles and js/ts modules in the component(s) itself.
The main styles make the most sense to import in the root component of the web component.
The reason why it has to be there is, due to:
https://github.com/vuejs/vue-cli/issues/6033 and
https://github.com/vuejs/core/issues/4662
that web components can't use plugins, or at least I don't know how. In other words there is no app.use() method.
I still couldn't properly import primeflex so I had to use the cdn link. I think it is possible to use an internal import, and I will update the answer when I find out how.
To use a specific PrimeVue component, simply import and register it as the documentation describes.
<template>
<Button />
</template>
<script lang="ts">
import Button from "primevue/button";
import { defineComponent } from "vue";
export default defineComponent({
components: { Button },
});
</script>
<style>
#import url("https://unpkg.com/primeflex#3.1.0/primeflex.css");
</style>
<style lang="scss" src="#/assets/scss/globals.scss"></style>
<style src="primevue/resources/primevue.min.css"></style>
<style src="primevue/resources/themes/tailwind-light/theme.css"></style>
//main.ts
import { defineCustomElement } from "vue";
import App from "./App.ce.vue";
customElements.define("custom-element", defineCustomElement(App));
Limitation:
Due to the missing plugin support (or my lack of knowledge of it) the lines:
import PrimeVue from 'primevue/config';
app.use(PrimeVue);
are not possible. Unfortunately, I can't fully grasp the impact that might have.

Uncaught TypeError: Bootstrap's JavaScript requires jQuery. jQuery must be included before Bootstrap's JavaScript. at Object.jQueryDetection

I am using Next.js App and trying to add jquery in the application but the issue is sometimes it work sometimes not, I already added it to top of the script.
import React from 'react';
import Head from 'next/head'
import Script from 'next/script';
const LoadCss = () => {
return ( <>
<Head>
<meta name="viewport" content="width=device-width,initial-scale=1"/>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css"/>
</Head>
</>
);
}
export default LoadCss;
import React from 'react';
import Script from 'next/script';
const LoadJs = () => {
return ( <>
<Script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></Script>
<Script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></Script>
<Script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.16.0/umd/popper.min.js"></Script>
</> );
}
export default LoadJs ;
and rest are loaded after this but still facing the issue.
I also try to load it via local folder but still no success.
Kinldy help

How to make ajax call with angular2/http?

I am using Angular 2.0.0-beta.0 with typescript. I was able to make ajax call with window['fetch'] out of the box without any problem (and I did not need to use any of the workarounds required in earlier versions.)
But I could not make the same ajax call working with angular2's http.
Here is the code to demo the issue. There are three files, index.html in the project folder, and boot.ts and app.component.ts in a subfolder called app.
app.component.ts:
import {Http, HTTP_PROVIDERS} from 'angular2/http';
import {Component} from 'angular2/core';
#Component({
selector: 'my-app',
providers: [HTTP_PROVIDERS],
template: '<h1>My First Angular 2 App</h1><button (click)="getTasks()">click</button>{{tasks}}'
})
export class AppComponent {
http: Http;
tasks = [];
constructor(http: Http) {
alert(http == null);
this.http = http;
}
getTasks(): void {
this.http.get('http://localhost:3000/tasks/norender');
//.map((res: Response) => res.json())
//it is important to have this subscribe call, since the
//request is only made if there is a subscriber
.subscribe(res => this.tasks = res);
}
}
boot.ts:
import {bootstrap} from 'angular2/platform/browser'
import {HTTP_PROVIDERS} from 'angular2/http';
import {AppComponent} from './app.component'
bootstrap(AppComponent, [HTTP_PROVIDERS]);
index.html:
<!DOCTYPE html>
<html>
<head>
<title>Angular 2 QuickStart</title>
<!-- 1. Load libraries -->
<script src="https://rawgithub.com/systemjs/systemjs/0.19.6/dist/system.js"></script>
<script src="https://code.angularjs.org/tools/typescript.js"></script>
<script src="https://code.angularjs.org/2.0.0-beta.0/angular2-polyfills.js"></script>
<script src="https://code.angularjs.org/2.0.0-beta.0/Rx.js"></script>
<script src="https://code.angularjs.org/2.0.0-beta.0/http.dev.js"></script>
<script src="https://code.angularjs.org/2.0.0-beta.0/angular2.dev.js"></script>
<!-- 2. Configure SystemJS -->
<script>
System.config({
transpiler: 'typescript',
typescriptOptions: {emitDecoratorMetadata: true},
packages: {'app': {defaultExtension: 'ts'}}
});
System.import('app/boot')
.then(null, console.error.bind(console));
</script>
</head>
<!-- 3. Display the application -->
<body>
<my-app>Loading...</my-app>
</body>
</html>
You should add an Http provider. You have two options:
On bootstrap:
import {HTTP_PROVIDERS} from 'angular2/http';
and:
ng.bootstrap(src.SomeComponent, [HTTP_PROVIDERS]);
On the component using the service:
import {HTTP_PROVIDERS} from 'angular2/http';
#Component({
...
providers: [HTTP_PROVIDERS]
...
})
I had a similar problem when I used an old version of the TypeScript compiler. I fixed it by changing the constructor argument from http: Http to #Inject(Http) http: Http. Of course, you need to import Inject to use it.
I'd try using the SystemJS release at https://code.angularjs.org/tools/system.js instead of the release at rawgithub.com.

Resources