Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How to set RTL as the default layout in new angular project #277

Open
aadenfr opened this issue Feb 18, 2025 · 8 comments
Open

How to set RTL as the default layout in new angular project #277

aadenfr opened this issue Feb 18, 2025 · 8 comments

Comments

@aadenfr
Copy link

aadenfr commented Feb 18, 2025

I'm trying to set RTL as the default layout but I am facing some issues with that, here is my try from the style.scss file
is there any way to make a switch lang in the navbar between Arabic/English

@import "variables";

// Import styles with default layout.
@import "@coreui/coreui/scss/coreui.rtl";

// Import Chart.js custom tooltips styles
@import "@coreui/chartjs/scss/coreui-chartjs";

// Custom styles for this theme
@import "theme";

// Some temp fixes
//@import "fixes";

// If you want to add custom CSS you can put it here.
@import "custom";

// Examples
// We use those styles to show code examples, you should remove them in your application.
@import "examples";
@xidedix
Copy link
Member

xidedix commented Feb 18, 2025

@aadenfr you're almost there.
In your src/index.html, add the dir attribute to the <html> tag and update the lang attribute to match your requirements.

<!DOCTYPE html>
<html lang="en" dir="rtl">
...
</html>

See also: https://coreui.io/bootstrap/docs/getting-started/rtl/#ltr-and-rtl-at-the-same-time

@aadenfr
Copy link
Author

aadenfr commented Feb 18, 2025

yes, it works 100% what about making dropdown switching lang do I need to implement that in scss like the dark/night feature or in a separate component?can you provide some help here!

@xidedix
Copy link
Member

xidedix commented Feb 18, 2025

@aadenfr It depends on your approach to language switching in your application. Whether you intend to use the built-in Angular Internationalization (https://angular.dev/guide/i18n) or a third-party dynamic runtime language switching solution (for example: https://ngx-translate.org), the method of switching languages is a secondary concern.

@aadenfr
Copy link
Author

aadenfr commented Feb 19, 2025

thanks for the comment , yes i'm planning to use ngx-translate , i just want a start do that using this combination of coreui prebuilts feature and ngx-translate

@xidedix
Copy link
Member

xidedix commented Feb 19, 2025

@aadenfr
In case of multiple languages, you could use a dropdown menu similar to the approach used for the dark/light theme feature. Other options include switch, radio, or radio toggle buttons.
I'd go for a separate component for language change. For toggling the dir attribute between rtl and ltr on an <html> tag, subscribe to TranslateService.onLangChange event.

@aadenfr
Copy link
Author

aadenfr commented Feb 19, 2025

after some research if found that there is a service called RtlService exists in @coreui/angular/lib/service/... but i don't know how to use

but i try with this stackblitz guide

readonly rtlMode =  this.#rtlService.isRTL(null); // can i use this???
 dir = 'rtl';
  toggleDir() {
    this.dir = this.dir === 'rtl' ? 'ltr' : 'rtl';
    const documentElement = this.document.documentElement;
    this.renderer.setAttribute(documentElement, 'dir', this.dir);
  }
// styles.scss
@import "@coreui/coreui/scss/coreui";
// _variables.c
 $enable-ltr: true;
 $enable-rtl: true;
//theme.scss can i do somthing like this ???
@if $enable-rtl {
  $enable-rtl:                  true !default;
  $enable-ltr:                  false !default;
}

@if $enable-ltr {
  $enable-ltr:                  true !default;
  $enable-rtl:                  false !default;
}

can i use this with ngx-translate to toggle the dir or there is same other best practices im missing?

@xidedix
Copy link
Member

xidedix commented Feb 19, 2025

@aadenfr

RtlService checks if the text direction of a document or an element is rtl.
The isRTL() method checks if the text direction is rtl:

  • If an element is provided, it checks if the element or any of its ancestors has the dir="rtl" attribute.
  • If no element is provided, it checks if the documentElement or body of the document has the dir="rtl" attribute.

If you need both ltr and rtl (that's your case), you should set both variables to true:

$enable-ltr: true;
$enable-rtl: true;

@import "@coreui/coreui/scss/coreui";

on upcoming v5.4 we support sass modules:

@use "@coreui/coreui/scss/coreui" as * with (
  $enable-ltr: true,
  $enable-rtl: true
);

Sass is a CSS preprocessor that converts Sass files into normal CSS that your web application can consume. The @if flow control rule is only applicable during the preprocessing phase. It does not work dynamically.

@aadenfr
Copy link
Author

aadenfr commented Feb 20, 2025

hello again I ended up with the following implementation to make it work ... is not ideal but I give it a try ... if someone needs it in the future.

1- update _variables.scss and keep only '"html lang="en"' in index.html
$enable-ltr: true !default;
$enable-rtl: true !default;

2- create new LanguageService

export class LanguageService {
  private LANGUAGE_KEY = 'app_language';
  private currentLang = new BehaviorSubject<string>('en');
  currentLang$ = this.currentLang.asObservable();

  constructor(private translate: TranslateService) {
    // Try to get language from localStorage first
    const savedLang = localStorage.getItem(this.LANGUAGE_KEY);

    if (savedLang && savedLang.match(/en|ar/)) {
      // Use saved language if it exists and is valid
      this.setLanguage(savedLang);
    } else {
      // Fall back to browser language or default
      const browserLang = translate.getBrowserLang();
      const defaultLang = browserLang?.match(/en|ar/) ? browserLang : 'en';
      this.setLanguage(defaultLang);
    }
  }

  setLanguage(lang: string) {
    // Save to localStorage
    localStorage.setItem(this.LANGUAGE_KEY, lang);

    // Update language
    this.translate.use(lang);
    this.currentLang.next(lang);

    // Update document attributes
    document.documentElement.lang = lang;
    document.documentElement.dir = lang === 'ar' ? 'rtl' : 'ltr';

    // Force layout refresh for RTL changes
    this.refreshLayout();
  }

  getCurrentLanguage(): string {
    return localStorage.getItem(this.LANGUAGE_KEY) || 'en';
  }

  private refreshLayout() {
    // Force a small layout refresh
    document.body.style.display = 'none';
    setTimeout(() => {
      document.body.style.display = '';
      // Dispatch resize event to help components adjust
      window.dispatchEvent(new Event('resize'));
    }, 0);
  }
}

3- in the DefaultHeaderComponent

export class DefaultHeaderComponent extends HeaderComponent {
....
readonly #languageService= inject(LanguageService)

switchLanguage(lang: string) {
    //window.location.reload();// use this if the refreshLayout not take the right effect
    this.languageService.setLanguage(lang);
  }
}

4- DefaultHeaderComponent template (you can make it with dropdow also)

<c-nav-item>
        <a cNavLink  routerLinkActive="active"  (click)="switchLanguage('en')"   >EN</a>
      </c-nav-item>
      <c-nav-item>
        <a cNavLink  routerLinkActive="active"  (click)="switchLanguage('ar')"  >Ar</a>
</c-nav-item>

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants