Use paperclip to upload from and display images in your Angular App

I have an Angular2 app from which I wanted to upload images to my Rails 5 API Server. I also want to show the uploaded image in another page in my app. This is how I accmoplished this:

Uploading

my.component.html

<input type="file" id="file" name="file" (change)="onLogoChange($event)" accept="image/png,image/jpeg" >

my.component.ts

In my component, I have a member variable called model, which I will eventually send to my Rails API in a POST request.

When the user selects a file, I encode it into base 64 and keep it in my model variable:

onLogoChange(e): void {
     let file: File = e.target.files[0]
     this.getFileBase64(file).then((base64: string) => {
         this.model.logoFileViewModel = new FileViewModel()
         this.model.logoFileViewModel.base64 = base64
         this.model.logoFileViewModel.name = file.name
     })
}

getFileBase64(file: File): Promise {
    let reader: FileReader = new FileReader()
    let promise = new Promise((resolve, reject) => {
        reader.onloadend = (e) => {
            resolve(reader.result)
        }
    })
    reader.readAsDataURL(file)
    return promise
}

When the user clicks on the ‘submit’ button that I have on my page, I send the model to the Rails API in a POST request. On the rails side, I have a model DefaultPageSetting and its controller DefaultPageSettingController.

default_page_setting.rb

class DefaultPageSetting < ApplicationRecord     
    has_attached_file :logo, default_url: "/images/default_page_setting/logo033.png", :styles => { :thumb => "100x100#" }
    validates_attachment :logo, presence: true
    do_not_validate_attachment_file_type :logo
end

def set_logo_from_view_model(view_model)
    file = Paperclip.io_adapters.for(view_model[:base64])
    file.original_filename = view_model[:name]
    self.logo = file
end

default_page_setting-controller.rb

def create
    @setting = DefaultPageSetting.new
    @setting.set_logo_from_view_model = params[:logo_file_view_model]
    @setting.save
end

And Voila! The file will be saved in subfolders inside app/system/default_page_settings/logos.

Displaying

default_page_setting.rb

def get_logo_file_view_model
    view_model = {}
    view_model[:name] = logo.name
    view_model[:thumb_url] = logo.url(:thumb)
    view_model[:url] = logo.url(:original)
    return view_model
end

default_page_setting_controller.rb

def show
    setting = DefaultPageSetting.first.as_json
    setting[:logo_file_view_model] = @setting.get_logo_file_view_model
    render json: setting
end

In my Angular component, once I receive the setting json from Rails using a GET request, I just prepend (not sure if its a valid English word :P) it with the base URL of the Rails API.

NOTE: You should consider keeping the Rails base URL in your environent.ts/environment.prod.ts and fetching it from there instead of hardcoding it.

my-show-page.component.ts

ngOnInit() {
    this.service.getPageSetting()
        .then((setting: DefaultPageSetting) => {
            this.setting = data.setting
            this.setting.logoFileViewModel.url = "http://localhost:3000" + data.setting.logoFileViewModel.url
    })
}

my-show-page.component.html

<img [src]="setting.logoFileViewModel.url" />

Helpful Resources:

How to use paperclip to add image attachment to your Rails model?
How to convert image to base64 in angular2?

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Create a free website or blog at WordPress.com.

Up ↑

%d bloggers like this: