Rails Image assets in AngularJS Directive and template

我的梦境 提交于 2019-12-08 07:58:21

问题


I have Rails 4 Application with AngularJS using these gems:

  • gem 'angularjs-rails'
  • gem 'angular-rails-templates'
  • gem 'asset_sync'

It works great with a template like this:

    <img ng-controller='LikePostController'  
       ng-dblclick='like(post);' 
       ng-src='{{post.photo.standard}}' 
       class='lazy post_photo pt_animate_heart'
       id='post_{{post.id}}_image'
     />

The Image render correctly. However in my other js

petto.directive('ptAnimateHeart', ['Helper', function(Helper){
    linkFunc = function(scope, element, attributes) {
      $heartIcon = $("#heart_icon");

      if($heartIcon.length == 0) {
        $heartIcon = $("<img id='heart_icon' src='/assets/feed.icon.heart.png' alt='Like' /> ");
        $(document.body).append($heartIcon);
      }

      element.on('dblclick', function(event){
        $animateObj = $(this);
        Helper.animateHeart($animateObj);
      });
    }
    return { 
      restrict: 'C',
      link: linkFunc
    }

  }])

I got 'assets/feed.icon.heart.png' was not found error from the browser console. I have feed.icon.heart.png located under app/assets/feed.icon.heart.png.

ps: Forget to mention I use assets sync gem to host assets in amazon s3. the image worked well in development but not in production.


回答1:


Hardcoded asset links only work in development because in production the assets get precompiled. Which means, amongst other things, the filename changes from:

my_image.png

into something like this (it adds and unique md5-hash):

"my_image-231a680f23887d9dd70710ea5efd3c62.png"

Try this:

Change the javascript file extension to: yourjsfile.js.erb

And the link to:

$heartIcon = $("<img id='heart_icon' src='<%= image-url("feed.icon.heart.png") %>' alt='Like' /> ");

For better understanding The Asset Pipeline — Ruby on Rails Guides




回答2:


You can define the following method somewhere in your helpers, e.g. in app/helpers/application_helper.rb:

def list_image_assets(dir_name)
  path = File.expand_path("../../../app/assets/images/#{dir_name}", __FILE__)
  full_paths = Dir.glob "#{path}/**.*"
  assets_map = {}
  full_paths.each do |p|
    original_name = File.basename p
    asset_path    = asset_path p[p.index("#{dir_name}")..-1]
    assets_map[original_name] = asset_path
  end
  assets_map.to_json
end

One can modify the method to work with any assets you wish, not just the ones located in subdirs of app/assets/images as in this example. The method will return a map with all the original asset names as keys and their 'compiled' names as values.

The map returned can be passed to any angular controller via ng-init (not generally recommended, but appropriate in this case):

<div ng-controller="NoController" ng-init="assets='<%=list_image_assets "images_dir_name"%>'"></div>

To make the assets really usable in angular, define a new $scope valiable in the controller:

$scope.$watch('assets', function(value) {
  if (value) {
    $scope.assets = JSON.parse(value);
  }
});

Having this in the $scope, it's possible to use assets names as usual, in e.g. ng-src directives, and this won't brake after the precompile process.

<img ng-src={{::assets['my_image.png']}}/>



回答3:


Just do the following:

app.run(function($rootScope,$location){
$rootScope.auth_url = "http://localhost:3000"   
$rootScope.image_url = $rootScope.auth_url + "/uploads/user/image/"
});

In controller inject dependency for $rootScope and in views

<img ng-src="{{user.image.url}}" width="100px" height="100px">

Note: It's working great in Rails API and it assumes that you've user object available so that it could specify the correct image in the /uploads/image/ directory



来源:https://stackoverflow.com/questions/23833963/rails-image-assets-in-angularjs-directive-and-template

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!