0
votes

currently I'm evaluating angular 4 / 5 and want to make the app look and feel "fancy" so I want to include materialzecss. I think I included the required .css and .js files correctly (although maybe not in the best way), because it looks fine so far.

But I'm struggling with the dynamic JavaScript. For example, in my navigation-component I want to call the necessary method

$(".button-collapse")).sideNav()

But it is not working. When I save this and open the page in browser, the console logs the error

TypeError: $(...).sideNav is not a function

So it seems that the mixins provided by the materialize.js file are not corretly loaded. I think this is a generic problem and not specific for materialize.

I already googled arround and found some answers but they didn't work for me.

So currently, my index.html looks like this:

<!doctype html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <title>myApp</title>
  <base href="/">

  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="icon" type="image/x-icon" href="favicon.ico">
  <link rel="stylesheet" href="https://fonts.googleapis.com/icon?family=Material+Icons">
  <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/css/materialize.min.css">
</head>

<body>
  <script type="text/javascript" src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/materialize/0.100.2/js/materialize.min.js"></script>
  <app-root></app-root>
</body>

</html>

The navigation.component.html looks like this:

<nav>
  <div class="nav-wrapper">
    <a routerLink="" class="brand-logo">&nbsp;myApp</a>
    <a href="#" data-activates="mobile-demo" class="button-collapse">
      <i class="material-icons">menu</i>
    </a>
    <ul class="right hide-on-med-and-down">
      <li>
        <a routerLink="link1">Link1</a>
      </li>
      <li>
        <a routerLink="link2">Link2</a>
      </li>
    </ul>
    <ul class="side-nav" id="mobile-demo">
      <li>
        <a class="subheader"></a>
      </li>
      <li>
        <div class="divider"></div>
      </li>
      <li>
        <a routerLink="link1" class="waves-effect">Link2</a>
      </li>
      <li>
        <a routerLink="link2" class="waves-effect">Link2</a>
      </li>
    </ul>
  </div>
</nav>

The navigation.component.ts looks like this:

import { Component, AfterViewInit } from '@angular/core';
import * as $ from 'jquery';

@Component({
  selector: 'app-navigation',
  templateUrl: './navigation.component.html',
  styleUrls: ['./navigation.component.css']
})
export class NavigationComponent implements AfterViewInit {
  ngAfterViewInit(): void {
    $(document).ready(function () {
      (<any>$(".button-collapse")).sideNav();
    });
  }

  constructor() { }
}

I think I'm missing an essential point here, maybe the way I include the files is wrong or I have to import something, but I don't get it.

Sidenote: I don't want to use angular material. I want to get this scenario to work.

Thank you guys!

Alex

3
$(".button-collapse")).sideNav() require jQuery. Did you import jQuery into your component? Make sure it is included in your package.json, not just included in the body. - Ringo
jquery itself is running. Otherwise the app would already break the line above where I call $(document).ready(...). But the app breaks inside the callback-function when I try to call the sideNav-method on the jquery-object. This is no native jquery-method, but it gets mixed-in by materialize. And this mixin is - what I think - not working. - Alex
I think the issue is that your jQuery instance with materialize.js from header got override by your package.json instance of jQuery. - Ringo

3 Answers

1
votes

I think your jQuery instance from header is being replaced by your import within the component.

To avoid this issue, use below in your component to let typescript know that there is already an instance of global jquery within your app.

declare var $: any;

as Niklas suggest in his answer, it is not recommend to use jQuery within Angular.

0
votes

You're probably missing jQuery

You should use angular modules rather than the basic bootstrap/materialize, which use jQuery

For bootstrap, I use ng-bootstrap https://ng-bootstrap.github.io/#/home

I don't know materializecss, but I found something that might help you https://github.com/InfomediaLtd/angular2-materialize

0
votes

If you want to use jQuery in combination with angular, you have to include it in your package.json.

Anyway I strongly suggest, that you switch from jQuery to specific angular frameworks for your purpose.

You can simply use Angular Material to get Material CSS and components. It also includes a sidenav ;) (OP did not want to use additional framework for his material CSS)

In that case it is general a good idea to just exclude jQuery and work with plain Angular. It should bring all the needed functions with itself.