Better practice for js i18n with angular - ruby-on-rails

I wonder to know if there is any bad smell on my practice for i18n on Angular.
I put the I18n translating function on Angular controller (because I don't know how to put it on HTML template file)
And about the i18n scope, I use this way I18n.t("city." + city_name) to indicate that the city_name is under "city" scope. Could I write it in this way I18n.t(city_name, scope: "city") to make it more understandable.
I appreciate every comment and suggestion to enhance my current solution.
Data structure
departures_lst is a list of countries' English name e.g.,: [US, China, Japan]
Each country has many cities name. e.g. [New York, LA, Boston]
Angular controller
App.controller("departures_ctrl", function($scope, $location, $http) {
$http.get("/departures.json")
.success(function (response) {
$scope.departures_lst = response;
});
$scope.get_destinations = function(city_name) {
return $location.url("/depart_from/" + city_name);
};
$scope.i18nCountryName = function(country_name) {
return I18n.t("country." + country_name) + country_name
};
$scope.i18nCityName = function(city_name) {
return I18n.t("city." + city_name) + city_name
};
});
HTML teamplate?
<div class="panel panel-transparent" ng-repeat="departure in departures_lst">
<h5>{{i18nCountryName(departure.country)}}</h5>
<li class="col-sm-3 col-lg-3 col-xs-3" ng-repeat="city in departure.cities">
<a ng-click="get_destinations(city)">
<i class="fa fa-plane"></i>
{{i18nCityName(city)}}
</a>
</li>
</div>

You should always try to put localization in the markup (as much as possible), that way you further encapsulate layout from your logic and data. I have always used the great angular-localization plug in. You get some great filters and directives to play with that have parametrization and other features built in. For example:
You have a string where you have to insert the name of a user, you define the string in your localized file as:
"some-loc-id-tag": "insert the user name {user} here!"
And in your controller scope have the property:
$scope.model.userName
And can display the name of the user with the localized string like so in HTML:
<div data-i18n="loc.some-loc-id-tag" data-user="{{model.userName}}"></div>
Check it out:
https://github.com/doshprompt/angular-localization

Related

text displaying in every form field

i'm making an Ember app with a Rails back end. In one of the templates, I list the available teams from a database and beside each team put a form field for the user to enter some textual information. If I enter information in one form field, the text appears in all of the form fields (kind of like a multiple cursor experience). That's one problem. Also, when I submit the button to attend one of the conferences, nothing's happening in the controller. I'm wondering if this is a related problem as Ember might think I'm trying to submit from multiple forms at one time due to the fact that these forms are acting as if they're the same form.
Can you see what I'm doing wrong?
<script type="text/x-handlebars" id="conferences">
<div class='span4'>
{{#each item in model}}
<li> {{#link-to 'conference' item}}
{{ item.name }}
{{ partial 'conferences/form'}}
{{/link-to }}</li>
{{/each}}
</ul>
</div>
<div class="span4 offset4">
{{ outlet}}
</div>
</script>
Inserted Form
<script type="text/x-handlebars" id="conferences/_form">
<form class="form-horizontal" {{action "attend" on="submit"}}>
<div class="controls">
{{input value=username type="text"}}
</div>
<button type="submit" class="btn">attend</button>
</form>
</script>
Conferences controller
App.ConferencesController = Ember.ObjectController.extend({
actions: {
attend: function() {
console.log('this is not logging, & no indication rails route is posted to)
$.post("/join_conference_path", {
username: this.get("username"),
}).then(function() {
document.location = "/";
}, function() {
}.bind(this));
}
}
});
Having all input values synced to the same text happen due to fact that each input value is bound to the same property username.
This happens because all _form partials are rendered in the same context which is in your case App.ConferencesController. To make them render in individual context use itemController argument for each helper. See spec here: http://emberjs.com/api/classes/Ember.Handlebars.helpers.html#method_each
{{#each item in model itemController="conference"}}
In this case I suggest you rename your App.ConferencesController to App.ConferenceController which will represent individual context for each "item". Having it done this way your action will always use username input for specific "item" only.
Action may not trigger because by default all actions targets routes and not controllers. Try to add target="controller" attribute to action helper:
{{action "attend" on="submit" target="controller"}}

Pass a parameter into partial view to use as query string name in action link?

I am trying to make this code a partial view to add alpha paging to my grids:
<div class="t-pager-wrapper" style="border-bottom:0">
<div class="t-pager t-reset">
#foreach (var letter in CollectionUtil.Alphabet){
#Html.ActionLink(letter, "Index", new { Equipment_filter = "Equipment.Name~startswith~'" + letter + "'" }, new { #class = "t-link" })
}
#Html.ActionLink("All", "Index")
</div>
</div>
How can I pass in the name "Equipment" to use as the parameter in the query string? All of my grids have their own name for their data, so in order for the paging filter to work it would be different on each page, Equipment_filter, Color_filter, Cars_filter, etc.
So example URLs would be:
http://www.mydomain.com/Equipment?Equipment-filter=Equipment.Name~startswith~'B'
http://www.mydomain.com/Color?Color-filter=Color.Name~startswith~'C'
So I would need to have parameters to pass into the partial being "Equipment" for the filter prefix, and "Equipment.Name" for the path to make the object property comparison with.
EDIT:
Well I did this by just using Url.Action inside the href parameter of a link instead:
#letter
At which point supplying "Equipment" and "Equipment.Name" are trivial since everything is a string. If someone wants to post a solution using ActionLink I will mark that as the answer though.
Well I did this by just using Url.Action inside the href parameter of a link instead:
#letter
At which point supplying "Equipment" and "Equipment.Name" are trivial since everything is a string.

Nested form trouble using Rails and AngularJS

I am fairly new to js and angular but I was trying to get a Rails app working after watching Ryan Bates's railscast on Rails+AngularJS (http://railscasts.com/episodes/405-angularjs?autoplay=true).
I believe what I want to do is fairly simple: I have a Place model that has many Phones and I want to dynamically be able to add and save phones when creating a new Place. This type of nested form is fairly easy in Rails alone (with js only creating a new field element when a user adds a Phone), but I want to do this in Angular.
I suppose my question then breaks down into two:
1) What is the best practice of creating nested forms in Rails+AngularJS (or even forms in general)? Right now I am passing every model to Angular via JSON but is this the best way?
My second question refers to the following code.
I've attempted to do this and I am able to save a Place in angular:
places_controller.rb
respond_to :json
def create
respond_with Place.create(params[:place])
end
_form.html.erb
<div class="container-fluid" ng-controller="PlaceCtrl">
<form ng-submit="addPlace()">
<div class="row-fluid">
<div class="span2"><label>Name</label></div>
<div class="span8"><input type="text" class="input-xlarge" ng-model="newPlace.name"></div>
</div>
<input type="submit" class="btn" value="Add">
</form>
</div>
place.js.coffee
app = angular.module("test", ["ngResource"])
app.factory "Place", ($resource) ->
$resource("/places/:id", {id: "#id"}, {update: {method: "PUT"}})
app.factory "Phone", ($resource) ->
$resource("/phones/:id", {id: "#id"}, {update: {method: "PUT"}})
#PlaceCtrl = ($scope, Place, Phone) ->
$scope.addPlace = ->
place = Place.save($scope.newPlace)
console.log place
$scope.newPlace = {}
In place.js.coffee I am able to save Place to the DB in the line (place = Place.save($scope.newPlace)). I want the id of place so I can append it to all Phones that are dynamically built (because Phones has a FK of place_id that points to a Place). However if I type in place.id in console, I get an undefined message. place.name will return the place's name, but id won't work. If I look at console.log place, however, I see that the id field is returned and populated.
2) How do I get the id field of the place JSON object? I am almost positive this is possible since Chrome's console returns the id field but place.id won't give me anything.
Thank you in advance for your help. I greatly appreciate it.
I would try something like this:
$scope.addPlace = ->
place = Place.save($scope.newPlace) ->
$scope.newPlaceId = place.id
console.log place
$scope.newPlace = {}

HTML in MVC RouteLink

I have a RouteLink constructed like so
<p class="articleLink">
#MvcHelper.Html.RouteLink(article.Title, "Article_Route", new RouteValueDictionary() { { "articleId", article.Id }, { "seoUrl", article.SeoUrl } }))
</p>
However, article.Title could potentially contain HTML i.e. the value could be <em>Sample</em> Title which in turn gets rendered like so
<em>Sample</em> Title
Is there any way to prevent the HTML from being escaped, and instead to be treated as actual HTML? Or do I need to create a standard HTML <a href... link in this case (thus losing all the niceties associated with the RouteLink helper).
If you want HTML inside your anchor don't use the Html.RouteLink (because it will HTML encode the link text by default as you noticed) instead of build your a tag by hand with using Url.RouteUrl to generate the url:
<p class="articleLink">
<a href="#(Url.RouteUrl("Article_Route",
new RouteValueDictionary()
{ { "articleId", article.Id },
{ "seoUrl", article.SeoUrl } }))">
#Html.Raw(article.Title)
</a>
</p>
Or you can create your own non encoding RouteLink helper.
You can use HtmlHelper.Raw(). Having said that, it is probably not a good idea to keep any HTML in your model/view model, which is against the principle of separation of model and presentation, also a security hazard.

how to BOLD a fragment of the linkText in an Html.ActionLink?

I have this:
<li><%:Html.ActionLink(user.Email.Replace(Model.SearchString, "<b>" + Model.SearchString + "</b>"), "LoginEdit", "Admin", new { area = "Staff", webUserKey = user.WebUserKey }, null)%>, last login: <%:loginString%></li>
As you can see, I want the portion of the Email string that matches the Model.SearchString to be bolded. I can't figure out the syntax to make this happen, given the context of my code.
Any ideas?
The goal is something like this (assuming user searched for "john"):
<b>john</b>#gmail.com
Whenever I encounter a situation likes this, I try my best not to embed HTML inside HTML helpers. In addition, I think breaking up your code will help in future maintenance - you're doing a lot in a single function call.
I would prefer doing it this way:
<li>
<a href="<%: Url.Action("LoginEdit", "Admin", new { area = "Staff", webUserKey =user.WebUserKey }) %>">
<%: user.Email.Replace(Model.SearchString, "") %>
<b><%: Model.SearchString %></b>
</a>
last login: <%: loginString %>
</li>
It's a few more lines of code, but it makes it much easier to decipher what's going on.
I think the issue is that the output of <%: %> is HTML encoded. So your <b> tag is probably encoded and you see the actual tag in the rendered HTML instead of the bold text.
If user.Email is a trusted value you could skip HTML encoding the output.
<li><%= Html.ActionLink(user.Email.Replace(Model.SearchString, "<b>" + Model.SearchString + "</b>"), "LoginEdit", "Admin", new { area = "Staff", webUserKey = user.WebUserKey }, null)%>, last login: <%:loginString%></li>
For more information see: http://haacked.com/archive/2009/09/25/html-encoding-code-nuggets.aspx

Resources