Base solution for your next web application
Open Closed

Angular 2 call service only on app initialization #3483


User avatar
0
moustafa created

Hello

I have Enum defined in core project that i use in many places of my application even in backend or frontend , the reason why i do this is if i decide to change values of Enum's properties would be in one place

namespace Umbrella.Models.Helpers
{
    public static class Enums
    {
        public enum CategoryType
        {
            Article = 1,
            Blog = 2,
            Faq = 3,
            Gallery = 4,
            News = 5,
            Service = 6,
            Video = 7,
            Work = 8,
            Slideshow = 9,
            Testimonial = 10
        }
    }
}

and i created controller in Web.Host project to retrieve that Enum as Json

namespace Umbrella.Web.Controllers
{
    public class EnumsController : UmbrellaControllerBase
    {
        [ResponseCache(Duration = Int32.MaxValue, Location = ResponseCacheLocation.Any)]
        public JsonResult Index()
        {
            var enumType = typeof(Enums.CategoryType);
            var enumDictionary = enumType
                .GetFields()
                .Where(x => x.IsLiteral)
                .ToDictionary(x => x.Name, x => (int)Enum.Parse(enumType, x.Name));
            var json = new JavaScriptSerializer().Serialize(enumDictionary);
            return Json(new {Data = json});
        }
    }
}

so to call this controller i use this url [http://localhost:22742/Enums]) and this is the output

{
result: {
data: "{"Article":1,"Blog":2,"Faq":3,"Gallery":4,"News":5,"Service":6,"Video":7,"Work":8,"Slideshow":9,"Testimonial":10}"
},
targetUrl: null,
success: true,
error: null,
unAuthorizedRequest: false,
__abp: true
}

in frontend i created EnumService to retrieve this Enum

import { Observable } from 'rxjs/Observable';
import { Injectable } from "@angular/core";
import { Http } from "@angular/http";
import { AppConsts } from '@shared/AppConsts';

@Injectable()
export class EnumsService {

    actionUrl = AppConsts.remoteServiceBaseUrl + '/Enums';
    enums: any;

    constructor(private _http: Http) {
        this.getEnums();
    }

    getEnums(): any {
        return this._http.get(this.actionUrl)
            .subscribe((result) => {
                this.enums = result.json().data;
            });

        // if (this.enums) {
        //     return Observable.of(this.enums);
        // } else {
        //     return this._http.get(this.actionUrl)
        //         .map(res => res.json())
        //         .do((data) => {
        //             this.enums = data;
        //         });
        // }
    }

}

what i need to do is to call EnumService only on app initialization (just once) so how can i achieve that ? is there any something wrong in my code or better way to achieve my goal? could you please explain to me the Observable object as i'm so confused ? and then how can i use these values in any components (ts,html) ? hope my questions are clear enough

Thanks


5 Answer(s)
  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi,

    Have you tried to get your enums in AppPreBootstrap.ts ? We use the same approach for getting application configuration, see <a class="postlink" href="https://github.com/aspnetzero/aspnet-zero-core/blob/dev/angular/src/AppPreBootstrap.ts#L15">https://github.com/aspnetzero/aspnet-ze ... rap.ts#L15</a>

    Thanks.

  • User Avatar
    0
    moustafa created

    Hi i'll try and let you know

    Thanks

  • User Avatar
    0
    moustafa created

    thank you it works just fine by adding this method and call it in AppPreBootstrap

    AppPreBootstrap.getEnums(callback);
    
    private static getEnums(callback: () => void) {
            return abp.ajax({
                url: AppConsts.remoteServiceBaseUrl + '/Enums',
                method: 'GET'
            }).done(result => {
    
                AppConsts.Enums = JSON.parse(result.data);
    
                callback();
            });
        }
    

    but i wounder if you can explain to me this methods in some details 1-

    static bootstrap<TM>(moduleType: Type<TM>, compilerOptions?: CompilerOptions | CompilerOptions[]): Promise<NgModuleRef<TM>> {
            return platformBrowserDynamic().bootstrapModule(moduleType, compilerOptions);
        }
    

    2- (callback: () => void) that exists in many methods

    thanks

  • User Avatar
    0
    alper created
    Support Team

    Glad that your problem is resolved ;)

  • User Avatar
    0
    ismcagdas created
    Support Team

    Hi @moustafa,

    1. This is a workaround for running one of two modules in angular app. Normally angular requires to bootstrap a single module but we have admin and account modules as you know. There was a bug in angular -cli, actually we had this problem when angular-cli was beta, so we applied this workaround. Maybe this is not required at the moment but we didn't change this code. So basically, it is a code for bootstrapping an angular module which was taken from angular's source codes.

    2. This is just a different way of calling a javascript function. Why we use it: Because when you call a function in typescript like this, "this" keyword points to current component, so we can easily access component's properties and methods.

    Thanks.