Angular view not updating properly on ng-click - javascript

Im writing selecting button menu and when I try to get to next select level nothing happens.
In first list item i want to write selected value from next level, in second I have successfully listed all items from first level and in third I want to display second (last) level oprions.
My code looks like:
<div ng-if="selected.type=='number' && selected.values[0].values">
<ul class="smsUl">
<li ng-if="selected.selected">
<button class="btn btn-warning btn-block">{{selected.selected}}</button>
</li>
<li ng-repeat="value in selected.values" ng-if="attributes == undefined">
<button class="btn btn-info btn-block" ng-click="$parent.attributes=value.values">{{value.value}}</button>
</li>
<li ng-repeat="attribut in attributes" ng-if="attributes != undefined">
<button class="btn btn-info btn-block" ng-click="selected.value=attribut.id; selected.selected=attribut.value; attributes=undefined">{{attribut.value}}</button>
</li>
</ul>
</div>
And part of jason with selected.values looks like:
[
{
"value": "clothing_glasses",
"values": [
{
"id": 1,
"value": "coat"
},
{
"id": 2,
"value": "glasses"
}
]
},
{
"value": "book_stationery",
"values": [
{
"id": 3,
"value": "book"
},
{
"id": 4,
"value": "document"
}
]
}
]
In nf-if expression I tried with:
!attributes
but nothing has changed.
Update:
If I set attribute variable in controller staticly it lists the content I want, but if I select, i should go back to the 1. level.

Are you sure you are not doing something like this in controller:
$scope.attributes = [someArray]
(bla bla, some code)
$scope.someOnClickFunction = function() {
$scope.attributes = [otherArray]
}
if so, than you are losing scope of the correct variable, and angular no longer watches what you think it should.
I reccomend creating some object called eg. "observable", put there all those 'attributes', 'selected' etc, and add to your controller:
$scope.$watchCollection('observable.attributes', function() {});
$scope.$watchCollection('observable.selected', function() {});
and when you want to change something in those arrays dont replace them (by applying new arrays to old variable).
If you dont want to play with pushgin, shifting, poping elements you can always use:
someDefinedArray.length = 0;
for-loop {
someDefinedArray.push(yoursobjects); //push objects back to array but with changes you wanted to make to array
}

Related

ng-mouseenter and ng-mouseleave not working inside an ng-repeat loop

I have an angular ng-repeat that displays list items inside of an unordered list. Within each list item, I have another unordered list of sub-items. Inside each sub-item <li>, I have a div to display a name and a div to store a value.
I am trying to hook up the ng-mouseenter and ng-mouseleave attributes to the value div, but they aren't firing. Even just trying to execute a console.log statement inside of the directives is not printing anything to the console.
I have no page load errors, everything displays on the page fine so angular is set up correctly, it's just ng-mouseenter and ng-mouseleave are not firing.
What do I have to do in order to get ng-mouseenter and ng-mouseleave to properly fire?
index.html
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.7/angular.js"></script>
<script src="js/app.js"></script>
<script src="js/SkillsetController.js"></script>
</head>
<body ng-app="mainApp">
<div id="skillset" ng-controller="SkillsetController">
<h2>{{title}}</h2>
<div class="skillListContainer" id="skillListContainer">
<ul class="skillCategoriesList">
<li class="skillCategory" ng-repeat="category in skillsetCategories">
<h3>{{category.title}}</h3>
<ul class="skillsList">
<li class="skill" ng-repeat="skill in category.skills">
<div class="skillName">
<span>{{skill.name}}</span>
</div>
<div class="skill-value" data-skill-value="{{skill.level}}"
ng-mouseenter="console.log('enter');"
ng-mouseleave="console.log('leave');">
{{skill.level}}
</div>
</li>
</ul>
</li>
</ul>
</div>
</div>
</body>
</html>
app.js
var app = angular.module("mainApp", []);
SkillsetController.js
app.controller("SkillsetController", ["$scope", function ($scope) {
$scope.title = "Skillset";
$scope.skillsetCategories = [
{
"title": "Backend",
"skills": [
{
"name": "Java",
"level": 10
}
]
},
{
"title": "Frontend",
"skills": [
{
"name": "HTML",
"level": 9
}
]
},
{
"title": "Frameworks",
"skills": [
{
"name": "jQuery",
"level": 9
}
]
},
{
"title": "Databases",
"skills": [
{
"name": "MySQL",
"level": 10
}
]
}
];
}]);
ng-mouseenter and ng-mouseleave work just fine in your code, just you can't call console.log in html directly, the functions you are using in your html template must be defined in your controller, try move console.log to your controller should resolve the problem.
index.html
<div class="skill-value" data-skill-value="{{skill.level}}"
ng-mouseenter="mouseEnter()"
ng-mouseleave="mouseLeave()">
{{skill.level}}
</div>
controller:
$scope.mouseEnter = function(){
console.log('enter');
};
$scope.mouseLeave = function(){
console.log('leave');
};
console.log() is not valid directly in the html
thats why you need to create those function to work
just change this add this function to your controller
$scope.mouseEnter = function(){
console.log("enter");
};
$scope.mouseLeave = function(){
console.log("leave");
};
and change this in the html
<div class="skill-value" data-skill-value="{{skill.level}}"
ng-mouseenter="mouseEnter()"
ng-mouseleave="mouseLeave()">
{{skill.level}}
</div>
Here is a example

how to datalink the index with the json object?

I have the following JSON object which maintain the sequence in it.
var sample={
"sample": [
{
"example": [
{
"sequence": 1,
},
{
"sequence":2
},
{
"sequence":3
}
]
},
{
"example": [
{
"sequence": 1,
}
]
}
]
};
$.templates("testingTemplate", "#testingSection");
var html=$.link.testingTemplate("#htmlHolder", sample);
$("#insert").click(function(){
var childIndexVal=parseInt($("#childIndex").val());
var x= {
"sequence": childIndexVal+1,
"xxx":"yyy"
};
var parentIndexVal=parseInt($("#parentIndex").val());
$.observable(sample.sample[parentIndexVal].example).insert(childIndexVal,x);
console.log(sample);
});
.parentHolder
{
border:1px solid red;
padding:5px;
margin:5px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jsviews/0.9.80/jsviews.js"></script>
<script id="testingSection" type="text/x-jsrender">
{{if sample && sample.length}}
{^{for sample }}
<div class="parentHolder">
{^{for example }}
<div><span data-link="#index+1" ></span>
<input type="text" value="{{:sequence}}" id="sequence" data-link="#index+1"></div>
{{/for}}
</div>
{{/for}}
{{/if}}
</script>
<div id="htmlHolder">
</div>
<div class="messages">
</div>
<span>Parent Index:</span><input type="text" id="parentIndex"/>
<span>Child Index:</span><input type="text" id="childIndex"/>
<button id="insert" >Insert</button>
so whenever I insert the object it should update the squence accodring to the index.
In the given example, if I am inserting an object into the 1st index of example in sample[0].(consider example array index starts from zero).
So when I am inserting one object into first parameter, the sequence in the remaining object should updated according to the index.
How can I achieve it.
give parent Index as 0 and child index as 1.
expected output,
Note: extra "xxx":"yyy" for differntiation purpose.
var sample={
"sample": [
{
"example": [
{
"sequence": 1,
},
{
"sequence": 2,
"xxx":"yyy"
}
{
"sequence":3
},
{
"sequence":4
}
]
},
{
"example": [
{
"sequence": 1,
}
]
}
]
};
Update: : tried with linkTo also.
<input type="text" data-link="linkTo=sequence #index+1" ></div>
Still not getting the expected output.
Thanks in advance.
Neither JsRender nor JsViews will modify the JSON data that they are rendering. This is by design: there are no side-effects on the data...
On the other hand, you can write code to create side-effects on the data, or you can use two-way binding so a user can modify data values. But two-way binding will only change the targetted data value, not other values elsewhere, and will do so only when the user triggers a change event on that <input> for example.
In your case you want any observable changes to an examples array to trigger changes to all examples in the array such as to ensure the example.sequence value is always equal to the index+1 for each example. In that case you have to write code to do that.
One way you can achieve that is to add the following code using observeAll:
$.observable(sample).observeAll(function(ev, eventArgs) {
if (ev.type==="arrayChange" && ev.data.observeAll.path().slice(-7)==="example") {
$.each(ev.currentTarget, function(i, item) {
$.observable(item).setProperty("sequence", i+1);
})
}
});
That will ensure that the sequence value stays in sync not only for insert, but also when items are removed or for changes in the the order of items, etc.

Filter with specific number of file txt in AngularJS

I have a problem in filter of angularjs. I've try to show the data which condition is ordering=1( it's in field in my file) but my code doesnt working.
Here is my code
<script>
function DanhMucController($scope, $http) {
var url = "data/cate.txt";
$http.get(url).success(function(response) {
$scope.DanhMucList = response;
});
}
</script>
Here is my html file
<div ng-app="" ng-controller="DanhMucController">
<ul class="list-unstyled">
<li ng-repeat="danhmuc in DanhMucList | limitTo:12">
{{danhmuc.career_name }}
</li>
</ul>
</div>
and my data file
[
{
"career_id": "1",
"career_name": "Cate1",
"depended": "0",
"ordering": "1"
},
{
"career_id": "2",
"career_name": "Cate2",
"depended": "0",
"ordering": "1"
},
{
"career_id": "3",
"career_name": "Cate3",
"depended": "0",
"ordering": "2"
}
]
The "limitTo" just get 12 first element. I wanna get to specific number.
it's look like sql: select * from table1 where ordering=1
Thanks for your answer
After the update, I am able to answer your question. The easiest solution is to have
<li ng-repeat="danhmuc in DanhMucList" ng-if="danhmuc.ordering == 1">
{{danhmuc.career_name }}
</li>
or
ng-if="danhmuc.ordering == '1'"
if the value is not an integer.
On 'ng-repeat' you need to filter array by "ordering" field, with value which you needed , '1' in your case
ng-repeat="danhmuc in DanhMucList | filter:ordering = 1"

Filter Embedded Json element from a Collection using AngularJS HTML

I'm having a JSON Collection, I wish to dispay Email ID which is marked as IsPreffered = TRUE using AngularJS HTML without .
user.Name
My JSON Collection :
{ "user" : [
{
"Name" : "B. Balamanigandan",
"Email": [
{
"Id": "bala#gmail.com",
"IsPreffered": true
},
{
"Id": "mani#gmail.com",
"IsPreffered": false
}
]}
]};
HTML Source Code:
<div>
<h3>Employee Details:</h3>
<span> {{collection.user.Name}} </span>
<span> {{collection.user.Email.Id}} </span>
</div>
The Collection user contains only one document. So, I didn't use ng-repeat. user is a Collection not a Document. One more check I need. If more than one email has `IsPreferred == true', then I have the take the last one. Kindly assist me.
Kindly filter the condition using HTML Level not in JavaScript Level. Kindly assist me.
instead of this:
<div>
<h3>Employee Details:</h3>
<span> {{collection.user.Name}} </span>
<span> {{collection.user.Email.Id}} </span>
</div>
you will have to do this:
<div>
<h3>Employee Details:</h3>
<span> {{collection.user[0].Name}} </span>
<span ng-repeat="email in collection.user[0].email| filter: {IsPreffered : 'true'}"> {{email.Id}} </span>
</div>
You have to use array syntax, because although there is only 1 user object, it is structured in the json as an array ( note the [ ] , same for Email).
Here is a fiddle: http://jsfiddle.net/Lvc0u55v/5593/
UPDATE: For showing only the last email which is true, use ng-if:
<span ng-repeat="email in collection.user[0].Email| filter: {IsPreffered : true} " ng-if="$last"> {{email.Id}}</span>
Here is the updated fiddle:
http://jsfiddle.net/Lvc0u55v/5594/
One way to do this is to use ngRepeat on the user Emails array with a filter to get only those Emails where "IsPreffered": true. The filter compares each object in the Emails array with the filter object (filterEmail). This filter object is defined in the controller - this way you will be able to change by demand or even set it dynamically.
var app = angular.module('app', []);
app.controller('ctrl', function($scope) {
$scope.collection = {
"user": {
"Name": "B. Balamanigandan",
"Email": [{
"Id": "bala#gmail.com",
"IsPreffered": true
}, {
"Id": "mani#gmail.com",
"IsPreffered": false
}]
}
};
$scope.filterEmail = {
"IsPreffered": true
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="app" ng-controller="ctrl">
<div>
<h3>Employee Details:</h3>
<span> {{collection.user.Name}} </span>
<span ng-repeat="email in collection.user.Email | filter : filterEmail ">
{{email.Id}}
</span>
</div>
</body>
NOTE: To my understanding it doesn't make much sense to have user as an array inside an object (in my example I removed the inner array). If you insist on keeping this data-schema, you will need to change every reference of collection.user to collection.user[0].

Nested ng-option inside angular ng-repeat

Im currently trying to nest a <select> inside a div with a ng-repeat
something like this:
<li ng-repeat="item in items >
<div class="row">
<div class="col-xs-7">
<span ng-bind="item.Name"></span>
</div>
<div class="col-xs-4 modal-body--ul--li__dropdown_container">
<select ng-model="typemodel" >
<option ng-repeat="usertype in item.userGroups"></option>
</select>
</div>
<div class="col-xs-1">
<a ng-click="add(item)"></a>
</div>
</div>
</li>
In the controller im adding the item to a new list with selected items. I also want to add the value from the dropdown as a new value to the list in the controller.
$scope.add = function (item) {
//New value with the value from the dropdown
item.recipientType = typemodel;
$scope.selected.push(item);
};
The list :
$scope.items = [
{
"Name":"Name1",
"userGroups":[
{ "type": "gruop1" },
{ "type": "gruop2" },
{ "type": "group3" }
]
},
{
"Name":"Name2",
"userGroups":[
{ "type": "gruop1" },
{ "type": "gruop2" },
{ "type": "group3" }
]
}
]
In short i need the selected value from the dropdown when i hit the "add", the value of the current typemodel.
This is how it looks now, but it dont work. I know i have to get the correct model and maybe track the items list by $index, but after searching the web the whole day for a solution, im still stuck!
All help is appreciated.
-Thanks!
ps. please comment if something is missing from the question, or something more is needed to solve this.
First, change your dropdown list to
<select ng-options="usertype in item.userGroups" ng-model="item.recipientType">
Then when you trigger the add function, item's property recipientType is already set.
$scope.add = function (item) {
console.log(item.recipientType);
$scope.selected.push(item);
};

Categories

Resources