AngularJS string interpolation not working? - javascript

For some reason, I can't seem to get string interpolation ({{}}) to work in my angularJS setup. I'm running with the MEAN stack I downloaded from here about a month ago and trying to replicate the angular-ui accordion example in my environment. In my template I have this:
<accordion close-others="true">
<accordion-group is-open="true" class="no-padding" ng-repeat="optSet in chartOptions">
<accordion-heading>{{optSet.name || 'broken...'}}</accordion-heading>
<div ng-include src="'option-content'" ng-init="options = optSet.data"></div>
</accordion-group>
</accordion>
then I have this in my controller:
$scope.chartOptions = [
{ 'name': 'Axis', 'data': chartAxisOptions }
];
but all I ever get is 'broken...' even though there's clearly a name attribute there as well. It's weird because it definitely renders based on the data I give it, but the name is not working at all. I have also tried adding it to the header attribute of the <accordion-group>, and making it check optSet['name'] as well -- the latter gives me undefined, in fact.

Unfortunately, the MEAN stack has some really weird setup issues. There was an issue with the Express twig templates, and angular interpolation. After making everything use angular, string interpolation worked again.

Related

Issues chaining object rendered from express in handlebars template

I'm having trouble finding the solution for a simple issue I'm currently having when trying to chain an object rendered from express in my handlebars file.
The object I'm trying to chain looks like so:
"generalContentOfferOne": {
"subCopy": {
"en-us": "Test Copy",
"bahasa": "Bergabunglah dalam..."
}
}
In my handlebars file, {{distributorJSON.generalContentOfferOne.subCopy}} renders Object object, which it should.
I have a localization variable I'm also rendering to handlebars. It will either be en-us or bahasa based on route. Anyways, now that I have this localization value, I figured I could use bracket notation to render the dynamic value in the object above. For example:
{{ distributorJSON.generalContentOfferOne.subCopy[{{localization}}] }}
Also tried:
{{ distributorJSON.generalContentOfferOne.subCopy.{{localization}} }}
These aren't working.. I'm guessing handlebars has it's own specific way to chain dynamic values? Or at least I hope so. Thanks for your help!
I couldn't find a default solution for this. So I built a handlebars helper.
Helper:
exports.returnDynamicPropValue = function(object, localization){
return object[localization];
}
Handlebars template:
{{ returnDynamicPropValue distributorJSON.generalContentOfferOne.subCopy localization }}

Using select2 addon with Ember cli

I'm kind of new to Emberjs and I'm having trouble using select2 addon.
The docs were completely useless, I couldn't get a single info from there. Now I want to make the user to be able to select multiple data gathered from the database I tried using "model" in the "content" section but it's not working.
Here is the sample I took from the docs
{{select-2
content=patients
value=patients
multiple=true
placeholder="Choose some Pizzas"
}}
and my controller
patients: Ember.computed(function(){
return this.store.findAll('patient')
}),
It sounds like I need to loop through the record from the database, either that or I need to follow a convention where the object needs to have an id, name and a description, I even tried to use "patient.name" but it won't work. I also tried to add the sample to a component "don't know why" but it made the whole app crashes and shows nothing but a white screen (no errors in the console).
A mentioned in comment, ember-select2 is deprecated in favour of power-select addon. You can view great documentation for all possibilities.
{{#power-select-multiple
options=patients
selected=name
placeholder="Select some names..."
onchange=(action (mut name))
as |patient|
}}
{{patient.name}}
{{/power-select-multiple}}
and in controller,
patients: Ember.computed('model',function(){
return this.store.findAll('patient')
}),
Here is the working twiddle for demonstration. to kick start your journey with power-select.

Blaze Meteor dynamically instanciate template and datacontext

I'm dynamically instanciating template on event / or array change (with observe-like functionality).
To achieve that, I use
//whatever event you want, eg:
$(".foo").on("click", function(){
Blaze.renderWithData(Template.widgetCard, d, $(".cards").get(0));
}
That is working, but obviously, instances aren't bound to any parent's template.
Because I just rendered this template on the div.cards I'm unable to use the Template.parentData(1) to get the parent datacontext, even so this div.cards is include on a template.
The quick fix would be to set the wanted reference (which in my case is an object) variable parent's datacontext on global scope, or even use Session, or directly pass this context through the renderWithData's data.
Do you know any other way,even better the proper one (I mean Meteor fancy one), to achieve that?
Is it a good Blaze.renderWithData use case?
Tell me if i'm unclear or more code is needed.
EDIT:
Complementary context info:
I've a chart (d3) where it's possible to select some parts of it.
It has an array property to stock this selected data part.
Chart = function Chart(clickCb, hoverCb, leaveCb, addSelectionCb, removeSelectionCb){
var chart = this;
chart.selectedParts = [];
//... code
}
From outside of this Chart class (so on the Meteor client side), the chart.selectedParts is modified (add/delete).
The dream would be to "bind" this array chart.selectedParts like:
Template.templateContainingAllThoseCards.helpers({
selectedDataChart: function(){
return Template.instance.chart.selectedParts;
},
//...
});
and on the template being able to do something like that:
<div class="row">
<div class="large-12 columns">
<div class="cards">
{{#each selectedDataChart}}
{{> cardWidget}}
{{/each}}
</div>
</div>
</div>
Like that, if the chart.selectedParts was reactive, Blaze could automatically create or remove cardWidget template instance due to the binding.
I've tried to use manuel:reactivearray package on it (and it's kind of anoying cause I'm doing complex manipulation on this array with Underscore, which obviously don't work with none-native Array type such reactiveArray).
Not working, but I dunno if it should have worked.
What do you think?
At this time, I'm doing things a bit dirty I suppose; I juste instanciate/destroying Blaze View on element added/removed chart.selectedParts as: Blaze.renderWithData(Template.widgetCard, {data: d, chart: this}, $(".cards").get(0));
So here how I manage to do that.
Actually I don't think using Blaze.renderWithData() is a good solution.
Best way I've found is to pass your data on "Reactive mode", to be able to use all Template functionalities, and keep using Spacebars to instanciate templates. (Like parent DataContext link).
Easiest way to have reactive datasource is to always match your data with your Mongo, so I don't have to declare a custom Reactive Data source (which could be tricky with complex from a complex js data structure).
If someone have the same problem, I'm pretty sure it's because you don't follow the "good" way to do (which was my case).
One con with always updating your DB as reactive Data source should be a case where you're doing a lot of UI state change, and after all, saving the change. On this case, it's pretty useless to always pass by the DB, but it's from far the quickest solution.
Ask me if you have any similar issue understanding philosophy/way to do, I'm starting to understand what i'm doing!

AngularJs testing. Where to put template

I am currently testing an angularjs directive. This directive has a templateUrl. I would lke to test the view to make sure it was initialized correctly i.e. correct number of buttons, certain elements hidden.
The problem I am having is that when I insert my html file into the template cache I still get :
"message": "Unexpected request: GET partials/stuff/stuff-leader.html
I assumed that when I used the templateCache I would no longer have to use:
$httpBackend.whenGET("partials/stuff/stuff-leader.html").respond([{
userId: 000
}]);
but this does not seem to be the case. I am wondering am I correctly inserting the template, here is how I am doing it:
template = $templateCache.get('/full/root/disk/path/to/file/stuff/stuff-leader.html');
$templateCache.put('/myApp/templates/stuff-leader.html',template);
Is this correct, or should I be placing it somewhere else?
Your normal template is looked for at /partials/stuff/stuff-leader.html, so this is what you need to inject into the template cache instead of /myApp/templates/stuff-leader.html.
You are performing a request with the $templateCache.get. Instead do:
beforeEach(inject(function ($templateCache) { $templateCache.put('partials/stuff/stuff-leader.html', '< div >...TemplateCode....< /div >'); }));

How to have an angularJS directive on a page called via ajax?

I have the following html (which can be accessed directly or called via ajax):
<section id="content" ng-controller="setTreeDataCtrl" get-subthemes>
<dl ng-repeat="subtheme in allSubthemes">
<dt>{{subtheme.Title}}</dt>
</dl>
Then I'm using the following directive:
myApp.directive('getSubthemes', function() {
return function($scope, element, attrs) {
$scope.allSubthemes = [];
angular.forEach($scope.data.Themes, function(value, key) {
angular.forEach(value.SubThemes, function(value2, key2) {
$scope.allSubthemes.push({
'ThemeTitle': value.Title,
'ThemeUrlSlug': value.UrlSlug,
'Title': value2.Title,
'UrlSlug': value2.UrlSlug
});
});
});
}
});
$scope.allSubthemes seems ok, but the dl's don't get rendered.
I can see for a second everything rendered properly and then it get's back to {{subtheme.Title}}, almost like it's being "unrendered"... any ideas of what I'm doing wrong?
Demo jsFiddle: http://jsfiddle.net/HMp3a/
rGil fixed the jsFiddle. It was missing a ng-app="pddc" declaration on an element so Angular did not know where to begin its magic.
I'd like to mention another way to render to the data in question. I suggest using an ng-repeat within an ng-repeat. See my forked & updated fiddle here. You can actually refer to the parent theme within the ng-repeat of the subtheme, so you don't have to copy values from the parent theme into each subtheme (which effectively eliminates the need for the directive in this example).
Another reason to use a nested ng-repeat is because of async issues that could come up when pulling data from a web service asynchronously. What could happen is when the directive executes, it may not have any data to loop through and populate because the data hasn't arrived yet.
If you use two ng-repeats, Angular will watch the $scope.data and re-run the ng-repeats when the data arrives. I've added a 500 ms delay to setting the data in my example to simulate web service latency and you'll see that even with the "latency", the data eventually renders.
There are two other ways around the async issue:
Use scope.$watch() in your directive, to watch for the data manually, or
Use the "resolve" functionality from Angular's routing feature to make sure the data is retrieved prior to controller execution.
While these alternative methods work, I think both are more complicated then just using two ng-repeats.

Categories

Resources