Using trustAsHTML for an array of Objects - javascript

I'm attempting to feed an array of objects from an Angular Controller to an ng-repeat directive.
The objects returned in the array have several properties, a few of which may contain HTML that needs to be output by the result of ng-repeat. I can't seem to figure out how to trustAsHTML the entire object that is returned.
My view looks like this:
<li ng-repeat="user in searchedUsers" ng-bind-html="user">
I've attempted it like this:
$scope.searchedUsers = data;
for(var user in $scope.searchedUsers){
$sce.trustAsHtml($scope.searchedUsers[user].matched);
$sce.trustAsHtml($scope.searchedUsers[user].unmatched);
}
And also attempted structuring my directives like this:
<li ng-repeat="user in searchedUsers"><span ng-bind-html="user.matched">{{user.matched}}</span> <span ng-bind-html="user.unmatched">{{user.unmatched}}</span></li>
But I get the error back:
Error: [$sce:unsafe] Attempting to use an unsafe value in a safe context.
The JSON object I'm using is as follows:
[{"id":2,"name":"Jonny","email":"jonnyasmar#me.com","created_at":"2015-10-25 00:58:10","updated_at":"2015-10-25 02:11:59","matched":"jonny<span class=\"match\">as<\/span>mar#me.com","unmatched":"Jonny"}]
Any idea how this can be accomplished or do I need to rethink my implementation?

You need to include ngSanitize js and dependency:
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.0/angular-sanitize.min.js"></script>
and, on module:
angular.module('yourModule', ['ngSanitize'])
after this, the ng-bind-html will work. For example:
<div ng-bind-html="user.matched"></div>
take a look at complete code on jsbin

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 }}

Lodash & Angular: Transform JSON object into view model

I am trying to find the best way to transform a large JSON object into a view model. Previously, I had the model incorporated into the view, which is a bad practice. So, now I have the model being generated inside of a controller. I am using Lodash as a utility library.
My current design plan is to transform the JSON object into a "master" array that is accessible in the controller's scope. The JSON file is being served by Express. ModelService simply gets this file to make it available in the controller.
$scope.arr is the "master" array that I want to use in the view.
I also made the JSON data available for viewing at an external link since it is so large. Here it is.
(function() {
'use strict';
angular
.module('app')
.controller('ModelController', ModelController);
function ModelController($scope, ModelService, _) {
$scope.jsonData = ModelService.getAll();
$scope.getData = function() {
$scope.jsonData.$promise.then(function(data) {
$scope.all = data;
$scope.arr = [];
_.mapValues($scope.all.parent1.clusters, function(cluster) {
$scope.arr.push(cluster.name);
_.mapValues(cluster.subclusters, function(subcluster) {
$scope.arr.push(subcluster.name);
_.mapValues(subcluster.entities, function(entity) {
// map entities
})
});
});
});
};
$scope.getData();
}
})();
This code is just adding cluster and subcluster names to the array. I'd like the subclusters to be mapped to their parent cluster. The idea I have for doing this involves transforming each cluster element into its own array, and then adding the subclusters, and then transforming each subcluster into an array in order to map the entities to them. This seems tedious and inefficient. So, I am looking for a better way to achieve this.
It would be nice if I could add each cluster object to the array in one fell swoop without all the mapping and converting objects to arrays. Is that possible at all?
The wireframe view looks like this. The Flex Cluster Title is the name of the subcluster, and each number inside of them is an entity.
Firstly, I would move this processing into the service. It's easier to test, and keeps your view separated from your models (Controllers, are really more part of the "View" IMO when it comes to Angular especially if you're considering upgrading to Angular 2.0 in the future).
In Angular, I think the appropriate way to solve this, would be to use components (or directives) combined with ng-repeat.
The page template:
<!-- Page template, assume $ctrl is your controller, $ctrl.clusters is the data -->
<cluster ng-repeat = "cluster in $ctrl.clusters"
cluster-data="cluster" >
</cluster>
The cluster directive template:
<!-- Assume $ctrl is the controller for the cluster directive, $ctrl.cluster is the cluster object. -->
<div class="name">{{$ctrl.cluster}}</div>
<div class="subClusterNames"
ng-repeat="subCluster in $ctrl.cluster.subClusters>
{{subCluster.name}}
</div>
You might think that this is mapping your data too closely to the view, but as long as you use components to display your data (ie, don't put it all into one template) I think you'll be fine.

In AngularJS, the data is showing up only in ng-repeat

I've got the following getUserData.js:
var App = angular.module('App', []);
App.controller('UserdataController', function($scope, $http) {
$http.get('data/getUserData.php')
.then(function(res){
$scope.users = res.data;
});
});
Which works perfectly, a Json is created inside the getUserData.php file, nothing wrong with that.
But when I want to display it inside the index.php file, I only get it to work using ng-repeat, like this:
<div ng-controller="UserdataController">
<ul>
<li ng-repeat="user in users">
{{user.voornaam}}
</li>
</ul>
</div>
But how can I display this data ("voornaam" is dutch for first name) without using ng-repeat? I thought it should be something like this, but it doesn't work..
<div ng-controller="UserdataController">
{{users.voornaam}}
</div>
Tried for several hours now, and searched all over the place. If someone can tell me what I'm doing wrong, that would be great!!
Well that's because users.vornaam just does not exists. However instead of showing an error Angular will just show a "blank value".
Check your object strucutre to understand your error. It will be something like
Users {
0:{ vornaam: xyz, ...}, //this is a single "user" which has a vornaam attribute
1:{ vornaam: xyz, ...},
2:{ vornaam: xyz, ...}
}
As you can see your Users object/array itself just does not have a "vornaam" but consists of several objects which then have the requested attribute.
In the above example
Users.vornaam
will be undefined. But if you try to access it like
Users[0].vornaam
it will work.

ng-click to trigger a function in app.js not working

I am learning javascript. I want to make a small chat app using angular js.
all of the data will be stored in javascript data structures - arrays, objects and be brought out to the front using angular js and styled with css.
now I have a button in index.html like this
<div class="container">
<button ng-click="createuser"></button>
</div>
in my js I have a controller where I am hanging an array called test on angular's $scope
$scope.tests = [ {'username': 'I am Joe'}];
I am looping through the tests array with ng-repeat in index.html
<li ng-repeat="test in tests">
{{test.username}}
</li>
now I have a method on the $scope object
$scope.createuser = function createuser() {
$scope.tests.push({'username': 'Mandy'})
};
that takes the array and use the push method (of the array) to push a sample object into the tests
but when I go to index.html and click, its not working because Mandy is not getting added to the loop.
Please note the method should see the $scope.tests because its all under one controller.
Forgot the ()
ng-click="createuser()"

angular js Service/Factory attributes behavior

I have a question about AngularJS behavior (JS behavior in general)
I have an Angular factory injected into a controller.
Here's a snippet of the controller code
$scope.localObjCollection= myObjFactorySvc.getObjCollection();
Let's assume that myObjFactorySvc.getObjCollection() returns the following object
[{"id":1"name":null,"address":null,"email":null},
{"id":2"name":null,"address":null,"email":null},
{"id":3"name":null,"address":null,"email":null},
{"id":4"name":null,"address":null,"email":null},
]
So, I'm pretty much using the factory to get the collection and storing it in $scope.localObjCollection.
My question is does $scope.localObjCollection have the value (copy) of the data returned by getObjCollection() or just a reference.
So if somewhere down in the controller source code, if I do
$scope.localObjCollection.push(newObj), does it also update the original collection in the Factory? It should I guess but I would like to understand the correct behavior
An array in JavaScript is an object and objects in JS are always passed/assigned by reference. Therefore your code would also update the original collection in the Factory, assuming that your myObjFactorySvc.getObjCollection() is something like this:
myObjFactorySvc.getObjCollection = function() { return someArrayVariable; }

Categories

Resources