html is not compile on append new child in angular js - javascript

I am trying to insert a node dynamically, but the appended html is not getting compiled correctly.
This is the code on Fiddle.
<body ng-app="app">
<div ng-controller="appController">
{{tittle}}
<div name="name" ng-repeat="d in data" ng-click="click(d.id)" id="div{{d.id}}">{{d.id}} click me</div>
</div>
(function () {
var app = angular.module('app', []);
app.controller('appController', function ($scope, $compile) {
$scope.tittle = "test";
$scope.data = [{ id: 1, child: [{name:'renjith'}] }, { id: 3 }, { id: 4 }, { id: 5 }, { id: 6 }];
$scope.click = function (data, $element) {
debugger;
var scope = { id: "12" };
angular.element(document.querySelector("#div" + data)).append($compile("<div ngTransclude>{{d.id}}</div>")($scope.data));
}
});
})();

Related

Filter with ng-repeat

I'm trying to make a filter with the angularJs directive called ng-repeat the filter works as follows:
When you click on the checkbox filters in an array the items that have offers, I'm using a function to filter, I think there is a better way to do it without so much code.
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope, $http, $document) {
$scope.items = [
{
id: 0,
description: "Primer Item 1",
offers: [
{
id: 0,
name: "Casa"
}
]
},
{
id: 1,
description: "Segundo Item 2"
},
{
id: 2,
description: "Tercer Item 3"
},
{
id: 3,
description: "Cuarto Item 4"
},
{
id: 4,
description: "Quinto Item 5"
},
{
id: 5,
description: "Sexto Item 5",
offers: [
{
id: 1,
name: "Bodega"
}
]
},
{
id: 6,
description: "Septimo Item 6"
},
{
id: 7,
description: "Octavo Item 7"
},
{
id: 8,
description: "Noveno Item 8"
},
{
id: 9,
description: "Decimo Item 9"
}
];
$scope.filterItem = function() {
if (!$scope.itemOffer){
$scope.filterOffer = function(item) {
return item.offers && item.offers.length > 0;
};
$scope.itemOffer = true;
} else {
$scope.filterOffer = function(item) {
return item;
};
$scope.itemOffer = false;
}
};
});
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
</head>
<body ng-app="myApp" ng-controller="myCtrl">
<input type="checkbox" name="filter" value="propertyOffer" ng-model="propertyOffer" ng-click="filterItem()">Item with offert
<div ng-repeat="item in items | filter: filterOffer track by $index">
{{ item }}
</div>
</body>
</html>
You can use ng-if with the ng-repeat directive to filter items containing offers at will :
JS CODE
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope, $http, $document) {
$scope.offersOnly = false;
$scope.items = [
// Your items
];
});
HTML CODE
<body ng-app="myApp" ng-controller="myCtrl">
<input type="checkbox" ng-model="offersOnly" ng-true-value="true" ng-false-value="false"/>
<div ng-repeat="item in items" ng-if="!offersOnly">
{{item}}
</div>
<div ng-repeat="item in items" ng-if="offersOnly && item.offers">
{{item}}
</div>
</body>

How to count the number of rows containing a certain value?

I'm using AngularJS and I have a table that I populate using ng-repeat. Check this short example:
http://jsfiddle.net/sso3ktz4/
How do I check how many rows I have with a certain value? For example, in the fiddle above, how do I check how many rows I have with the word "second"? It should return "3".
AngularJS answers are preferred, although I also have JQuery available.
Thanks!
updated controller code is below, where $scope.findRowCount is required function
var myApp = angular.module('myApp', []).controller('MyCtrl', MyCtrl);
function MyCtrl($scope) {
$scope.items = [{
name: 'first',
examples: [{
name: 'first 1'
}, {
name: 'first 2'
}]
}, {
name: 'second',
examples: [{
name: 'second'
}, {
name: 'second'
}]
}];
$scope.findRowCount=function(value){
var count=0;
angular.forEach($scope.items, function(item, i){
if(item.name==value){
count=count+1;
}
angular.forEach(item.examples, function(exp, j){
if(exp.name==value){
count=count+1;
}
})
});
console.log("count"+count);
return count;
}
var result=$scope.findRowCount("second");
console.log(result);
}
http://jsfiddle.net/p3g9vyud/
Try this way
var myApp = angular.module('myApp', []).controller('MyCtrl', MyCtrl);
function MyCtrl($scope) {
$scope.items = [{
name: 'first',
examples: [{
name: 'first 1'
}, {
name: 'first 2'
}]
}, {
name: 'second',
examples: [{
name: 'second'
}, {
name: 'second'
}]
}];
//Get sum based on the label
$scope.getTotalByLabel = function(keyword)
{
$scope.totalSecond = 0;
angular.forEach($scope.items, function(value, key) {
if(value.name == keyword)
{
$scope.totalSecond += 1;
}
angular.forEach(value.examples, function(val, k) {
if(val.name == keyword)
{
$scope.totalSecond += 1;
}
});
});
return $scope.totalSecond;
}
}
th,
td {
padding: 7px;
text-align: left;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.1/angular.min.js"></script>
<div ng-app="myApp">
<div ng-controller="MyCtrl">
<table border="1">
<tbody ng:repeat="i in items">
<tr>
<td>{{i.name}}</td>
<td>{{$index}}</td>
</tr>
<tr ng:repeat="e in i.examples">
<td>{{e.name}}</td>
<td>{{$index}}</td>
</tr>
</tbody>
</table>
<b>Total of second</b>: {{getTotalByLabel('second')}}
</div>
</div>

Issue with scope of a custom directive

Hi I have a directive like,
mainApp.directive('myMenu',function(){
return {
restrict : 'E',
scope :{menuItems : "=menuItems"},
compile: function(element, attributes) {
var linkFunction = function($scope, element, attributes){
for (i = 0;i<$scope.menuItems.length;i++){
element.append('<li>'+$scope.menuItems[i].name+'</li>');
}
}
return linkFunction;
}
}
});
I am using it like below in my HTML
<my-menu menuItems="menuItems"></my-menu>
But in the console I am getting an error like
TypeError: Cannot read property 'length' of undefined
The problem could be that, then the linking phase is executed the menuitems may not be loaded so $scope.menuItems may be undefined.
A better solution could be
var mainApp = angular.module('my-app', [], function() {})
mainApp.controller('AppController', function($scope) {
$scope.menuItems = [{
name: 'one'
}, {
name: 'two'
}, {
name: 'three'
}, {
name: 'four'
}];
})
mainApp.directive('myMenu', function() {
return {
restrict: 'E',
scope: {
menuItems: "="
},
template: '<ul><li ng-repeat="item in menuItems">{{item.name}}</li></ul>'
}
});
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.js"></script>
<div ng-app="my-app" ng-controller="AppController">
<my-menu menu-items="menuItems"></my-menu>
</div>
If you can't use template then
var mainApp = angular.module('my-app', [], function() {})
mainApp.controller('AppController', function($scope) {
$scope.menuItems = [{
name: 'one'
}, {
name: 'two'
}, {
name: 'three'
}, {
name: 'four'
}];
})
mainApp.directive('myMenu', function() {
return {
restrict: 'E',
scope: {
menuItems: "=menuItems"
},
link: function($scope, element, attributes) {
$scope.$watch('menuItems', function(value) {
element.empty();
angular.forEach(value, function(item) {
element.append('<li>' + item.name + '</li>');
});
});
}
}
});
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.js"></script>
<div ng-app="my-app" ng-controller="AppController">
<my-menu menu-items="menuItems"></my-menu>
</div>
The Issue was with the name I used, like menuItems in directive should be equal to menu-items, solved the issue by repalcing the menuItems to menu.
use $scope.$eval(attributes.menuItems) inside compile function to get menuItems

Check value of ng-model against string and do function

I have a few functions that I'm having to mix because of scope in a < select :
HTML:
<!-- COUNTRY -->
<select class="account--select" type="text" name="country" ng-model="data.country_id"
ng-options="o.code as o.name for o in content.countries" ng-change="reset();PookycountryChanged()">
<option value="">OTHER*</option>
</select>
Directive:
scope.PookycountryChanged = function() {
scope.$watch('data.country_id', function(){
if ('data.country_id' == "OTHER*") {
console.log('this is the other option selected');
}
});
}
AIM:
To be able to have a function run when the value of the option selected is equal to 'OTHER*'. Right now this is set to a simple console.log. Getting nothing in the console at the momento.
Any pointers?
UPDATE with Reset() function:
scope.reset = function(){
scope.isenabled = (scope.data.country_id == content.config.pca_country);
scope.country = _.findWhere(scope.content.countries, {code : scope.data.country_id});
};
scope.reset();
UPDATE 2:
Generated markup:
<select ng-change="reset()" ng-options="o.code as o.name for o in content.countries" ng-model="data.country_id" name="country" type="text" class="account--select ng-scope ng-valid ng-dirty"><option value="" class="">OTHER*</option><option value="0" selected="selected">United Kingdom</option></select>
Now you have a few problems with your code: in PookycountryChanged you not check value for data.country_id just create yet another watch, also in watch you compare string 'data.country_id' with string "OTHER*" so it always false.
In case where you select item with value="" model set value to null so in watch function you can check it like in snippet below.
angular.module('app', [])
.controller('ctrl', function($scope) {
$scope.reset = function() {
$scope.isenabled = ($scope.data.country_id == $scope.content.config.pca_country);
$scope.country = _.findWhere($scope.content.countries, {
code: $scope.data.country_id
});
};
$scope.content = {
config : {pca_country: 3},
countries: [{
code: 1,
name: 'name1'
}, {
code: 2,
name: 'name2'
}, {
code: 3,
name: 'name3'
}, {
code: 4,
name: 'name4'
}, {
code: 5,
name: 'name5'
}, {
code: 6,
name: 'name6'
}, {
code: 7,
name: 'name7'
}]
};
$scope.$watch('data.country_id', function(newVal) {
if (newVal === null) {
console.log('selected others');
}
})
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.2/angular.js"></script>
<div ng-app="app" ng-controller="ctrl">
<select class="account--select" type="text" name="country" ng-model="data.country_id" ng-options="o.code as o.name for o in content.countries" ng-change="reset();">
<option value="">OTHER*</option>
</select>
{{country}}
</div>
Or you can avoid even your reset function
angular.module('app', [])
.controller('ctrl', function($scope) {
$scope.content = {
config: {
pca_country: 3
},
countries: [{
code: 1,
name: 'name1'
}, {
code: 2,
name: 'name2'
}, {
code: 3,
name: 'name3'
}, {
code: 4,
name: 'name4'
}, {
code: 5,
name: 'name5'
}, {
code: 6,
name: 'name6'
}, {
code: 7,
name: 'name7'
}]
};
$scope.$watch('data.country_id', function(newVal, oldVal) {
if (newVal !== oldVal && !newVal) {
console.log('selected others');
}
})
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.2/angular.js"></script>
<div ng-app="app" ng-controller="ctrl">
<select class="account--select" type="text" name="country" ng-model="country" ng-options="o.name for o in content.countries" ng-change="data.country_id=country.code;isenabled=country.country_id==content.config.pca_country">
<option value="">OTHER*</option>
</select>
{{country}}
</div>
Remove PookycountryChanged() from your ng-change, then remove the function wrapping your $watch. There is no point having a watcher inside a function since the watch will always be running anyways.
Also change your option to this:
<option value="OTHER*">OTHER*</option>
Then you need to remove the quotation marks around data.country_id:
scope.$watch('data.country_id', function(){
if (data.country_id === "OTHER*") {
console.log('this is the other option selected');
}
});

passing different array variables to directive

In a controller I have defined two different arrays and I need to pass different arrays to directives, but the same item array is getting passed only.
Actually this is just snippets. In my actual code this directive I am using inside another.
Is that causing problem or any other way?
<div my-sticky tags="items" template_name="test2.html"></div>
<div my-sticky tags="kititems" template_name="test2.html"></div>
JS:
app.controller('MyCtrl', function($scope, $http) {
$scope.items = [
{ id: 18, text: '1' },
{ id: 28, text: '2' },
{ id: 38, text: '3' }
];
$scope.kititems = [
{ id: 0, text: '001' },
{ id: 028, text: '002' },
{ id: 038, text: '003' }
];
});
app.directive("mySticky", function($http, $compile) {
return {
restrict : "A",
scope : {
templateName: "#",
tags: "=",
},
templateUrl : function(el, attrs) {
return attrs.templateName;
},
controller : function($http, $scope, $element, $sce, $templateCache, $compile, $attrs) {
$scope.drawerStyle = {left: '140px'};
//$scope.CommonArray=$attrs.tags;
},
replace : false,
transclude : false,
link : function(scope, element, attrs) {
// change element just to show we can
}
};
});
Try this one
Working Demo
Inside your templateURL(test2.html) should like this i.e,
<div ng-repeat="tag in tags"> {{tag.id}} {{tag.text}} </div>
You might try to access items or kititems both are not in current scope because you have used isolated scope here.For clarity template used here instead of templateURL.
HTML Markup:
<div ng-controller="MyCtrl">
MyCtrl
<div my-sticky tags="items"></div>
<hr/>
<div my-sticky tags="kititems"></div>
</div>
angular modules
var app = angular.module("myApp",[]);
app.controller('MyCtrl', function($scope) {
$scope.items = [
{ id: 18, text: '1' },
{ id: 28, text: '2' },
{ id: 38, text: '3' }
];
$scope.kititems = [
{ id: 0, text: '001' },
{ id: 028, text: '002' },
{ id: 038, text: '003' }
];
});
app.directive("mySticky", function($http, $compile) {
return {
restrict : "A",
scope : {
templateName: "#",
tags: "=",
},
template :'<div ng-repeat="tag in tags"> {{tag.id}} {{tag.text}} </div>',
controller : function($http, $scope, $element, $sce, $templateCache, $compile, $attrs) {
$scope.drawerStyle = {left: '140px'};
// console.log($scope);
//$scope.CommonArray=$attrs.tags;
},
replace : false,
transclude : false,
link : function(scope, element, attrs) {
// change element just to show we can
}
};
});

Categories