Meterial Design javascript method from Angular 7 component - javascript

*Solved it by using: 'declare var md:any;' after imports *
I am building a website in which I am using 'creative tim template for dashboard'
I am using date and time picker, the issue I am facing is the DateTime picker is initialized only once and 'it worked when the component and loaded for the first time but when I switch components then DateTime picker stop working',
the solution that I've found out is I have to initialize DateTime picker every time component is loaded by using the initialize method in the component
but then I receive the error src/app/components/booktrip/booktrip.component.ts(24,5): error TS2304: Cannot find name 'md'.
here's my code
import { Component, OnInit } from '#angular/core';
import { FormBuilder, FormGroup,FormControl, Validators } from '#angular/forms';
import { Trip } from '../../mockups/trip.mockup';
#Component({
selector: 'app-book-trip',
templateUrl: './book-trip.component.html',
styleUrls: ['./book-trip.component.css']
})
export class BookTripComponent implements OnInit {
constructor(private formBuilder: FormBuilder) { }
ngOnInit() {
md.initFormExtendedDatetimepickers();
}
bookTrip(trip) {
console.log(trip);
}
}
My angular.json is
"scripts": [
"src/assets/js/core/jquery.min.js",
"src/assets/js/core/popper.min.js",
"src/assets/js/core/bootstrap-material-design.min.js",
"src/assets/js/plugins/perfect-scrollbar.jquery.min.js",
"src/assets/js/plugins/moment.min.js",
"src/assets/js/plugins/sweetalert2.js",
"src/assets/js/plugins/jquery.validate.min.js",
"src/assets/js/plugins/jquery.bootstrap-wizard.js",
"src/assets/js/plugins/bootstrap-selectpicker.js",
"src/assets/js/plugins/bootstrap-datetimepicker.min.js",
"src/assets/js/plugins/jquery.dataTables.min.js",
"src/assets/js/plugins/bootstrap-tagsinput.js",
"src/assets/js/plugins/jasny-bootstrap.min.js",
"src/assets/js/plugins/fullcalendar.min.js",
"src/assets/js/plugins/jquery-jvectormap.js",
"src/assets/js/plugins/nouislider.min.js",
"src/assets/cdnjs.cloudflare.com/ajax/libs/core-js/2.4.1/core.js",
"src/assets/js/plugins/arrive.min.js",
"src/assets/buttons.github.io/buttons.js",
"src/assets/js/plugins/chartist.min.js",
"src/assets/js/plugins/bootstrap-notify.js",
"src/assets/js/material-dashboard.min40a0.js",
"src/assets/demo/demo.js",
"src/assets/demo/jquery.sharrre.js"
]
and the error i am getting is
Error
I am not able to generate production build.
I am stuck for too long.. is there any possible solution ??

I think it's only a TypeScript error, and that md is actually defined -it's just that TypeScript doesn't know about it-.
Have you tried importing it directly to the files where you use md?
import * as md from 'material-dashboard';
You can read more about it here: https://hackernoon.com/how-to-use-javascript-libraries-in-angular-2-apps-ff274ba601af
This is how I think your component should look like, in the end:
import { Component, OnInit } from '#angular/core';
import { FormBuilder, FormGroup,FormControl, Validators } from '#angular/forms';
import { Trip } from '../../mockups/trip.mockup';
import * as md from 'material-dashboard';
#Component({
selector: 'app-book-trip',
templateUrl: './book-trip.component.html',
styleUrls: ['./book-trip.component.css']
})
export class BookTripComponent implements OnInit {
constructor(private formBuilder: FormBuilder) { }
ngOnInit() {
md.initFormExtendedDatetimepickers();
}
bookTrip(trip) {
console.log(trip);
}
}

Related

Sending calculated data from one component to another without Services

I want to send the value from one component to another, they are not related so all solutions are saying that I must use shared service to do that. But these services are using templates (if I'm right). Is there a way to do this sharing without services?
I want to send the BMI value from homepage.component.ts to result.component.ts.
homepage.component.ts:
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-homepage',
templateUrl: './homepage.component.html',
styleUrls: ['./homepage.component.css']
})
export class HomepageComponent implements OnInit {
constructor() { }
myHeight!:number;
myWeight!:number;
bmi!:number;
ngOnInit(): void {
}
onGenerate( height:string,width:string){
this.myHeight = +height;
this.myHeight=Math.pow(this.myHeight/100,2);
this.myWeight = +width;
this.bmi=this.myWeight/this.myHeight
console.log(this.bmi); //this is the calculated value to send
}
}
result.component.ts:
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-result',
templateUrl: './result.component.html',
styleUrls: ['./result.component.css']
})
export class ResultComponent implements OnInit {
constructor() { }
//I want to get the bmi here
ngOnInit(): void {
}
}
There are Two ways to communicate between unrelated components in angular:
1 - Through services, you have to understand where to inject it, in your case I think it should be injected in root, so try this with your service ( follow this tutorial to implement your service, just add my code instead of theirs )
#Injectable({
providedIn: 'root',
})
2 - Through a store ( a lot of boilerplate coding, to use if you have complexe states to keep synchronized through the whole app, by the way the store is basically a service )
If your components are not related then you can create a shared service between them. Then, you need to use dependency injection to communicate between these components. So, there is a great Angular tutorial which describes how to do it.
The service code would look like this:
#Injectable()
export class FooService {
constructor( ) { }
private yourData;
setData(data){
this.yourData = data;
}
getData(){
let temp = this.yourData;
this.clearData();
return temp;
}
}
and sender component:
import { Router } from '#angular/router';
import { FooService} from './services/foo.service';
export class SenderComponent implements OnInit {
constructor(
private fooService: FooService,
private router:Router) {}
somefunction(data){
this.fooService.setData(data);
this.router.navigateByUrl('/reciever');//as per router
}
}
and subscriber:
import { Router } from '#angular/router';
import { TransfereService } from './services/transfer.service';
export class RecieverComponent implements OnInit {
data;
constructor(
private fooService: FooService){
}
ngOnInit() {
data = this.transfereService.getData();
console.log(`data: `, data)
}
}
Solution: To pass the data from one component to another we can store it in a session storage or a local storage and then access it in other components from that storage. Here I have provided a sample code using local storage for your reference.
homepage.component.ts:
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-homepage',
templateUrl: './homepage.component.html',
styleUrls: ['./homepage.component.css']
})
export class HomepageComponent implements OnInit {
constructor() { }
myHeight!:number;
myWeight!:number;
data:string='';
bmi!:number;
ngOnInit(): void {
}
onGenerate( height:string,width:string){
this.myHeight = +height;
this.myHeight=Math.pow(this.myHeight/100,2);
this.myWeight = +width;
this.bmi=this.myWeight/this.myHeight;
this.data=localStorage.setItem('bmi',this.bmi);
console.log(this.bmi); //this is the calculated value to send
}
}
resultcomponent.ts:
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-result',
templateUrl: './result.component.html',
styleUrls: ['./result.component.css']
})
export class ResultComponent implements OnInit {
data:any;
constructor() { this.data=localstorage.getItem('bmi')}
//Access the bmi using the data variable here
ngOnInit(): void {
}
}

Angular 6 - Adding script at component level and checking if it exists

I have a script that I would like to run on one component only. I have managed to achieve adding the script on the component but a couple of things happen that I'm not entirely sure how to resolve.
If I navigate to the component, the script is added to the DOM, but it isn't firing. If I refresh the page, it works
If I navigate away to another component and return, the script is added again, and it can keep building up
component.ts
import { Component, OnInit } from '#angular/core';
import { Renderer2, Inject } from '#angular/core';
import { DOCUMENT } from '#angular/platform-browser';
#Component({
selector: 'app-privacy',
templateUrl: './privacy.component.html',
styles: []
})
export class PrivacyComponent implements OnInit {
constructor(private _renderer2: Renderer2, #Inject(DOCUMENT) private _document) {
let s = this._renderer2.createElement('script');
s.type = `text/javascript`;
s.src = `../../assets/scripts/privacy.js`;
this._renderer2.appendChild(this._document.body, s);
}
ngOnInit() {
}
}
You need to add the onload (if you need to support IE make sure to also support onreadystatechange) handler to your script element which can call a function you want to execute when the script is finished loading.
To remove the script onNgDestroy, save a reference of createElement? on the Component and remove this in Destroy lifecycle hook.
import { Component, OnInit, OnDestroy } from '#angular/core';
import { Renderer2, Inject } from '#angular/core';
import { DOCUMENT } from '#angular/platform-browser';
#Component({
selector: 'app-privacy',
templateUrl: './privacy.component.html',
styles: []
})
export class PrivacyComponent implements OnInit, OnDestroy {
private s: any;
constructor(private _renderer2: Renderer2, #Inject(DOCUMENT) private _document) {
this.s = this._renderer2.createElement('script');
this.s.type = `text/javascript`;
this.s.src = `../../assets/scripts/privacy.js`;
this.s.onload = this.doneLoading;
this._renderer2.appendChild(this._document.body, this.s);
}
doneLoading () {
// do what you need to do
}
ngOnDestroy() {
// this removes the script so it won't be added again when the component gets initialized again.
this._renderer2.removeChild(this._document.body, this.s)
}
ngOnInit() {
}
}
Your approach in running this js file is wrong, you should do following to achieve this in the clean way:
Add your js file to the assets (for example assets/js/privacy.js)
Add file to the .angular-cli.json scripts
Now you can call your js functions from angular components if you declare them in the component
angular-cli.json
"scripts": [
"assets/js/privacy.js"
]
component.ts
import { Component, OnInit } from '#angular/core';
declare function myFunc(): any; // function from privacy.js
#Component({
selector: 'app-privacy',
templateUrl: './privacy.component.html',
styles: []
})
export class PrivacyComponent implements OnInit {
constructor() {
}
ngOnInit() {
myFunc(); // call it
}
}

getting ExpressionChangedAfterItHasBeenCheckedError Angular 4

Im aware similar questions exist but none of those have provided me with an answer that works..
Basically I have a site with some services that inject data dynamically
In my app.component.ts I have two headers.. one when your on the home page and one for when your on any other page
app.component.html
<app-header *ngIf="router.url !== '/'"></app-header>
<app-header-home *ngIf="router.url != '/'"></app-header-home>
<router-outlet></router-outlet>
<app-footer></app-footer>
app.component.ts
import { Component } from '#angular/core';
import { Router } from '#angular/router';
#Component({
selector: 'app-root',
templateUrl: './app.component.html',
styleUrls: ['./app.component.scss']
})
export class AppComponent {
title = 'app';
router: string;
constructor(
private _router: Router
) {
this.router = _router.url;
}
}
now I also have a service that dynamically injects the title of the header
headerTitle.service.ts
import { Injectable } from '#angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
#Injectable()
export class HeaderTitleService {
title = new BehaviorSubject('');
constructor() { }
setTitle(title: any) {
this.title.next(title);
}
}
then In my home component for example I set the title
home.component.ts
import { Component, OnInit, AfterViewInit } from '#angular/core';
import { HeaderTitleService } from '../../services/headerTitle.service';
import { HeaderImageService } from '../../services/headerImage.service';
#Component({
selector: 'app-home',
templateUrl: './home.component.html',
styleUrls: ['./home.component.scss']
})
export class HomeComponent implements OnInit {
constructor(
private headerTitleService: HeaderTitleService,
private headerImageService: HeaderImageService
) { }
ngOnInit() {
}
ngAfterViewInit() {
this.headerTitleService.setTitle(`
We strive to create things
<br> that are engaging, progressive
<br> & above all
<span class="highlight">
<em>innovative.</em>
</span>
`);
}
}
now basically it was all working until I put in the if statements on the two headers
now Im getting this error
Error: ExpressionChangedAfterItHasBeenCheckedError: Expression has changed after it was checked. Previous value: ''. Current value: '
We strive to create things
<br> that are engaging, progressive
<br> & above all
<span class="highlight">
<em>innovative.</em>
</span>
'.
not sure how I can fix this.. I tried setting the values in ngAfterViewInit but it did nothing
or does anyone know another way I could accomplish this??
Thanks
You can try using a setTimeOut method instead and set the values
inside of that
setTimeout(this.headerTitleService.setTitle(`
We strive to create things
<br> that are engaging, progressive
<br> & above all
<span class="highlight">
<em>innovative.</em>
</span>
`), 0);
note this is a work around and not a full proff solution to the problem .
To know why this error occurs in Angular change detection you need to know how the change detection works in Angular for this you can refer to this blog by Maxim NgWizard K
I know i fixed this in mine.
here is a great post
everything-you-need-to-know-about-the-expressionchangedafterithasbeencheckederror
i have forced the change detection
export class AppComponent {
name = 'I am A component';
text = 'A message for the child component';
constructor(private cd: ChangeDetectorRef) {
}
ngAfterViewInit() {
this.cd.detectChanges();
}

Confusing behavior of a BehaviorSubject in my Angular App

I recently ran into a problem and can't really figure out what's wrong with my code at this point, hopefully someone of you can help me.
All I am trying to do is changing the value of my BehaviorSubject with a function but it isn't working out.
chat.service.ts
import { Injectable } from '#angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
#Injectable()
export class ChatService {
chatId = new BehaviorSubject<number>(0);
constructor() {
this.chatId.next(1);
}
changeChatId(chatId: number) {
console.log(chatId);
this.chatId.next(chatId);
}
}
So the subscribers get the default as well as the changed chatId from the constructor. But as soon as I try to change it with the changeChatId function nothing happens at all. The right id's get passed into the function I already debugged that but the line this.chatId.next(chatId) doesn't seem to do anything.
ADD
These are the other components the service is currently used in.
chat-message-list
import { Component, OnInit, Input} from '#angular/core';
import { ChatService } from "../../../shared/services/chat.service";
#Component({
selector: 'app-chat-message-list',
templateUrl: './chat-message-list.component.html',
styleUrls: ['./chat-message-list.component.css'],
providers: [ChatService]
})
export class ChatMessageListComponent implements OnInit {
chatId: number;
constructor(private chat: ChatService) { }
ngOnInit() {
this.chat.chatId.subscribe(
chatId => this.updateMessageList(chatId)
);
}
}
chat-item
import { Component, OnInit, Input} from '#angular/core';
import { User } from '../../../shared/models/user.model';
import { ChatService } from '../../../shared/services/chat.service';
#Component({
selector: 'app-chat-list-item',
templateUrl: './chat-list-item.component.html',
styleUrls: ['./chat-list-item.component.css'],
providers: [ChatService]
})
export class ChatListItemComponent implements OnInit {
#Input()
user: User;
constructor(private chat: ChatService) { }
ngOnInit() {
}
onChatItemSelected(){
this.chat.changeChatId(this.user.id);
}
}
You need to make your ChatService a singleton (shared) service. Add it to the providers of your ngModule. This allows all the components that use the ChatService to share the same service instance.
#NgModule({
providers: [ChatService]
})
And remove it from your components providers. When you are adding it to your components providers, that component gets its own instance of ChatService which can not be used by other components.

Angular 2 Failed to compile

i created a new component in angular 2 with this:
ng g component todos
So it created the new component, I went to the component and I noted that I had a new folder with the files:
todos.component.css, todos.component.html, todos.component.spec.ts, todos.component.ts
Then I openened todos.component.ts and it had:
import { Component, OnInit } from '#angular/core';
#Component({
selector: 'app-todos',
templateUrl: './todos.component.html',
styleUrls: ['./todos.component.css']
})
export class TodosComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}
Then I put the new second line because I am learning with a tutorial:
import { Component, OnInit } from '#angular/core';
import { TodosComponent } from './todos/todos.component';
#Component({
selector: 'app-todos',
templateUrl: './todos.component.html',
styleUrls: ['./todos.component.css']
})
export class TodosComponent implements OnInit {
constructor() { }
ngOnInit() {
}
}
When I did that and I ran the server it showed me this:
Failed to compile.
C:/angular2/proyecto/src/app/todos/todos.component.ts (2,10): Individual declarations in merged declaration 'TodosComponent' must be all exported or all local.
I'd like to know what is it bad? why does it show that error?
Thanks!
You are importing the class into it's own file.
No need to import your own component, you should import it in other files, where you use it.

Categories