ng-bind-html not working - javascript

I'm trying to insert HTML into my div (bottom of code). I've dealt with an issue like this before so I added a filter. However, when the div is made visible through a toggle function the HTML doesn't display from the service. I have verified that the service is returning the proper HTML code.
The div is unhidden but no html is displayed.
Angular Code:
var myApp = angular.module('myApp', []);
angular.module('myApp').filter('unsafe', function ($sce) {
return function (val) {
if ((typeof val == 'string' || val instanceof String)) {
return $sce.trustAsHtml(val);
}
};
});
myApp.controller('myAppController', function ($scope, $http) {
...
SERVICE CODE
...
$scope.toggleHTMLResults();
$scope.HTMLjson = obj[0].HTML;
HTML Code:
<div id="returnedHTML" ng-bind-html="HTMLjson | unsafe " ng-hide="HTMLResults">NOT HIDDEN</div>
I'm not sure why this isn't working.
Here is my Plunker

There were multiple things wrong with your example.
Main Javascript file declared twice, first in header and second before close on body tag
You call a function as HTMLAPI() instead of $scope.HTMLAPI()
Your $scope.HTMLAPI() function was also being called before it was initialised
Fixed controller code:
app.controller('myAppCTRL', ['$scope', '$http', function ($scope, $http) {
var API = this;
$scope.HTMLInput = true;
$scope.HTMLResults = true;
$scope.toggleHTMLInput = function () {
$scope.HTMLInput = $scope.HTMLInput === false ? true : false;
}
$scope.toggleHTMLResults = function () {
$scope.HTMLResults = $scope.HTMLResults === false ? true : false;
}
$scope.HTMLAPI = function (HTML) {
var newJSON = ["[{\"ConditionId\":1111,\"ConditionDescription\":\"<i>DATA GOES HERE</i>\",\"ErrorId\":0,\"DisplayId\":0,\"DisplayName\":\"\",\"ErrorValue\":\"\"}]"];
var obj = JSON.parse(newJSON);
$scope.HTMLjson = obj[0].ConditionDescription;
$scope.toggleHTMLResults();
console.log($scope.HTMLjson);
}
$scope.HTMLAPI();
}]);
Working Example

Related

Angular - removing class after time

I am building a sort of (faux) loader in Angular. Currently, I have this:
const app = angular.module('app', []);
app.controller('loaderCtrl', ($scope, $timeout) => {
let loading = $scope.loading,
loaded = $scope.loaded;
$scope.reset = () => {
$timeout(() => {
loading = false;
loaded = false;
console.log(loaded);
}, 500);
}
});
HTML:
<main ng-app="app">
<div ng-controller="loaderCtrl as loader" >
<div class="loader" ng-class="{ '-loading' : loader.loading === true, '-loaded' : loader.loaded === true }"></div>
<button ng-click="loader.loading = true;">loading</button>
<button ng-click="loader.loaded = true; reset();">loaded</button>
</div>
</main>
CodePen: http://codepen.io/tomekbuszewski/pen/WrXXdp
My problem is, both loading and loaded aren't being set up for my view, so the classes are permanently there. What can I do?
So, this is a problem of scope. Basically when you do this
let loading = $scope.loading,
loaded = $scope.loaded;
You get the "value" of the variables inside Angular scope. Therefore Angular does not know anything about changes made to those
The fix is simple, don't do that, but instead
$scope.reset = () => {
$timeout(() => {
$scope.loading = false;
$scope.loaded = false;
}, 500);
}
Why not using an object and change its content? It is possible to do that as #beaver pointed out, but then you have another problem, you need to trigger the digest cycle yourself via $apply. And somewhere in your code, you might accidentally change the content of the object and it might affect other part of the system
Having said that I do not know Babel and so I worked on the JS compiled version, I noticed that you assigned loader.loading and loader.loaded to variables and then used those "references" in $timeout function.
As in javascript
Primitives are passed by value, Objects are passed by "copy of a
reference"
you have to use $scope.loader.loading and $scope.loader.loaded
app.controller('loaderCtrl', function ($scope, $timeout) {
$scope.loader = {};
var loading = $scope.loader.loading, loaded = $scope.loader.loaded;
$scope.reset = function () {
$timeout(function () {
$scope.loader.loading = false;
$scope.loader.loaded = false;
}, 500);
};
});
Here I forked your CodePen: http://codepen.io/beaver71/pen/wMPprm

Setting value of dropdown programmatically

I have a directive which I want to change the value of on a click event. This is the controller that the click event is being triggered (I have removed all irrelevant code) :
(function () {
"use strict";
//getting the existing module
angular.module("app")
.controller("teamsController", teamsController);
//inject http service
function teamsController($scope, $http, divisionService, $rootScope) {
$scope.divisions = divisionService.all();
var vm = this;
vm.teams = [];
vm.newTeam = {};
vm.editTeam = function (team) {
$rootScope.$broadcast('someEvent', [team.division]);
}
And here is where the event is being captured :
(function () {
"use strict";
//getting the existing module
angular.module("app")
.controller("divisionsController", divisionsController)
.directive("divisionDropdown", divisionDropdown);
//inject http service
function divisionsController($http, $scope, divisionService, $rootScope) {
$scope.divisions = divisionService.all();
$rootScope.$on('someEvent', function (event, selectedDiv) {
alert(selectedDiv);
$rootScope.selectedDivision = selectedDiv;
});
};
function divisionDropdown() {
return {
restrict: "E",
scope: false,
controller: "divisionsController",
template: "<select class='form-control' ng-model='selectedDivision' ng-options='division.divisionName for division in divisions' required>\
<option style='display:none' value=''>{{'Select'}}</option>\
</select>"
};
}
})();
And this is the divisionService, which I am using to populate the dropdown intially :
app.factory("divisionService", function ($http) {
var divisions = [];
var errorMessage = "";
var isBusy = true;
//matched to verb, returns promise
$http.get('http://localhost:33201/api/Divisions')
.then(function (response) {
//first parameter is on success
//copy response.data to vm.divisions (could alternatively use a foreach)
angular.copy(response.data, divisions);
}, function (error) {
//second parameter is on failure
errorMessage = "Failed to load data: " + error;
})
.finally(function () {
isBusy = false;
});
return {
all: function () {
return divisions;
},
first: function () {
return divisions[0];
}
};
});
But I am not able to get the selectedDivision in the dropdown to change on the click event. Can anybody tell me how do I refer to it and reset it? I am not that familiar with scoping in Angular so my usage of $scope and $rootScope is possibly where the issue lies.

AngularJs Counter to count up to a specific target number

I am trying to create a counter using Angularjs which should count up to a number which is already present in that division. Here is my html snippet.
<div class="circle-home">
<span class="circle-home-score " id="counterofreviews" data-count="{{noReviews}}">{{noReviews}}</span> REVIEWS
</div>
Now when I am trying to get the value inside the span I get it as {{noReviews}} instead of its value.
Here is my AngularJs code.
var demoApp = angular.module(['demoApp','ngRoute','ui.bootstrap']);
demoApp.controller('SearchController',function ($scope, $http, $facebook, $interval){
$scope.noReviews=100;
$scope.childOnLoad = function() {
$scope.uppercount=$("#counterofreviews").text();
$scope.no_Reviews=0;
console.log($scope.uppercount);
var stop;
stop = $interval(function() {
if ($scope.uppercount >$scope.no_Reviews) {
$scope.noReviews=$scope.no_Reviews;
$scope.no_Reviews++;
console.log('Inside if statement');
} else {
$scope.stopFight();
}
}, 100);
};
$scope.stopFight = function() {
if (angular.isDefined(stop)) {
$interval.cancel(stop);
stop = undefined;
}
};
$scope.childOnLoad();
};
Output of console.log($scope.uppercount) is {{noReviews}}. I am unable to figure out a proper way to do it. Please suggest the correction or any other better method for the same perpose.
Not sure why do you use jQuery to get the #counterofreviews value. Is the value there because it's added from a server side script?
As mentioned in the comments, your code is probably not working because jQuery.text() is returning a string. Using parseInt(text) could work.
Please have a look at the demo below and here at jsfiddle.
It's more Angular and should help you getting started with your counter.
var demoApp = angular.module('demoApp', []); //'ngRoute','ui.bootstrap']);
demoApp.controller('SearchController', function ($scope, $http, $interval) { //$facebook,
$scope.noReviews = 100;
//$scope.childOnLoad = function () {
this.upperCount = 10; //$("#counterofreviews").text();
console.log(this.upperCount);
var stop;
this.startCounter = function () { // needed for re-run on change
//console.log(stop, this);
this.no_Reviews = 0;
if ( angular.isUndefined(stop) )
stop = $interval(checkCount.bind(this), 100);
};
this.startCounter();
//};
function checkCount() {
if (this.upperCount >= this.no_Reviews) {
this.noReviews = this.no_Reviews;
this.no_Reviews++;
//console.log('Inside if statement');
} else {
stopFight();
}
}
function stopFight() {
if (angular.isDefined(stop)) {
$interval.cancel(stop);
stop = undefined;
}
};
//$scope.childOnLoad();
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="demoApp" class="circle-home" ng-controller="SearchController as ctrl">Review max.:
<input ng-model="ctrl.upperCount" ng-change="ctrl.startCounter()"/> <span class="circle-home-score " id="counterofreviews" data-count="{{ctrl.upperCount}}">{{ctrl.noReviews}}</span> REVIEWS</div>

Angular Inter-Directive Communication

I have created the following simple code with several directives (I have experience with Angular only for several months).
I have used unusual way to make some basic inheritance (as You can see from the Directive class), parameters by default (using ||), possibility to insert one element into another (using transclude), have added directory-specific controllers and of course, specified the link function to support DOM events handlers.
Currently I am trying to call function specified in another directory controller through it's scope, but it fails. The error is 'Uncaught TypeError: undefined is not a function'.
My target is to call controller's function independently from the DOM structure (the target element could be sibling, parent or child). I have considered also shared service and broadcast events, but it seems not the right way to make the communication.
Why the code doesn't work properly?
Are there any other ways to make it?
Thanks in advance.
HTML
<body ng-app="app">
<component id="button" name="button">
</component>
<icon name="icon">
</icon>
</body>
JS
(function() {
var app = angular.module('app', []);
app.directive('icon', function() {
var directive = new Directive();
return directive;
});
app.directive('button', function() {
var directive = new Directive();
return directive;
});
function Directive(options) {
options = options || {};
this.scope = options.scope || {
name: '#'
};
this.restrict = options.restrict || 'E';
this.replace = (options.replace != null) ? options.replace : true;
this.transclude = (options.transclude != null) ? options.transclude : true;
this.template = options.template || '<div ng-transclude></div>';
this.controller = function($scope) {
$scope.focus = function() {
console.log('focus');
};
$scope.outFocus = function() {
console.log('outFocus');
};
};
this.link = options.link || function($scope, $element, $attrs) {
$element.click(function() {
$scope.focus();
var _scope = angular.element('#button').scope();
_scope.outFocus(); // doesn't work
});
};
}
})();

How to set ng-disabled inside directive

My directive has
link: function ($scope, $elm, $attrs) {
var status = $scope.item.status
if (status) {
var statusName = status.name,
item = $scope.item;
if (statusName === 'USED') {
$attrs.$set('ng-disabled', true); // this doesn't work
} else {
$elm.attr('ng-disabled', false);
}
}
}
So, my question is:
How to apply ng-disabled to element with this directive?
if (statusName === 'USED') {
$attrs.$set('disabled', 'disabled');
} else {
$elm.removeAttr('disabled');
}
Why invoke ng-disable at all? You're already once evaluating the condition yourself, so having ng-disable evaluating it again is redundant.
You would set ng-disabled to a scope variable, ex:
<input ng-disabled="isDisabled" />
And then inside your directive you can set that variable:
$scope.isDisabled = true;
//html
<div ng-app="miniapp" ng-controller="MainCtrl">
<input type="submit" mydir>
</div>
//js
'use strict';
var app = angular.module('miniapp', []);
app.directive('mydir', function ($compile) {
return {
priority:1001, // compiles first
terminal:true, // prevent lower priority directives to compile after it
compile: function(el) {
el.removeAttr('mydir'); // necessary to avoid infinite compile loop
return function(scope){
var status = scope.item.status
if (status === 'USED') {
el.attr('ng-disabled',true);
} else {
el.attr('ng-disabled',false);
}
var fn = $compile(el);
fn(scope);
};
}
};
});
app.controller('MainCtrl', function ($scope) {
$scope.item = {};
$scope.item.status = 'USED';
});
credit to Ilan Frumer

Categories

Resources