Json model not binding in angular - javascript

Angular 1 app here.
I have this json file named data.json:
[
{
"rejectionType": "REJECTION_1",
"user": "ALL",
"selected": false
},
{
"rejectionType": "REJECTION_2",
"user": "MALE",
"selected": false
},
{
"rejectionType": "REJECTION_3",
"user": "FEMALE",
"selected": false
}
]
In controller I do the following:
$http.get('data.json').then(function(response) {
var rejectionData = response.data;
myctrl.currentRejections = _.filter(rejectionData, function(item, index) {
return _.contains(["ALL", "MALE"], item.user);
})
console.log("myCtrl.currentRejections:",myCtrl.currentRejections);
$("#modRejectionReason").modal("show");
});
The modal in the view looks like this:
<div id="modRejectionReason">
<div class="modal-body">
<p>
<div ng-repeat="allrejections in myctrl.currentRejections">
<p>
<input type="radio" name="selected" ng-model="allrejections.selected" />
{{allrejections.rejectionType}}
</p>
</div>
</p>
</div>
<div class="modal-footer">
<button type="button" ng-click="myctrl.func()">OK</button>
</div>
</div>
</div>
</div>
And then in the controller I have this:
var declineInvite = function () {
console.log("myctrl.currentRejections:",myctrl.currentRejections);
}
In the log I see that when the modal appears, then the variable myCtrl.currentRejections is printed. And it is an array with all the filtered elements.
For each element I see that the field selected is false.
When I then check a radio button and then click on the OK-button the function func is triggered.
Even here the same data is printed in the console. However, for those radio buttons that have been clicked in the json the value for the field selected is undefined.
What am I missing here?

You need to give the radio buttons a value to set when they are checked.
<input type="radio" name="selected" ng-model="allrejections.selected" ng-value="true"/>
The problem with doing this in your current code is that the selected:true will never be unset, so I suggest adding a new value on the controller called selectedRejection and using that as the model and setting the value to the actual rejection object. Doing this means you can get rid of the selected property on your JSON data too!
var myApp = angular.module('myApp', []).controller("MyCtrl", MyCtrl);
//myApp.directive('myDirective', function() {});
//myApp.factory('myService', function() {});
function MyCtrl() {
var MyCtrl = this;
MyCtrl.currentRejections = [{
"rejectionType": "REJECTION_1",
"user": "ALL",
"selected": false
},
{
"rejectionType": "REJECTION_2",
"user": "MALE",
"selected": false
}
]
MyCtrl.selectedRejection = null;
MyCtrl.submit = function() {
console.log(MyCtrl.selectedRejection)
}
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<body ng-app="myApp">
<div ng-controller="MyCtrl as MyCtrl">
<div ng-repeat="allrejections in MyCtrl.currentRejections">
<p>
<input type="radio" name="selected" ng-model="MyCtrl.selectedRejection" ng-value="allrejections" /> {{allrejections.rejectionType}}
</p>
</div>
<button type="button" ng-click="MyCtrl.submit()">OK</button>
</div>
</body>

Related

Bind data based on the drop down selection from JSON input in AngularJS

I hope you guys are doing good in this pandemic time and spare some time to help me out.
I am trying to filter the data based on the drop-down selections of a drop-down list. Here I will get the data from the JSON input.
Here in the Filing Date, I have selected 06/30/2022 so for this date the below region offices are available.
So if I change the date to any another date like 07/30/2022 it is showing only 2 region offices
And if we expand the + icon it should display the values like below. That is the requirement and I am done with writing the code for expanding collapse functionality.
However, I am not sure how I need to bind the data associated with the date and display below. Here is the code I have written
var app = angular.module('acturial', ['ui.bootstrap']);
////configure routes
//// TODO:Will implement and configure routes but for now it is not needed
//app.config(function ($routeprovider) {
// $routeprovider
// // route for default page
// // in our case only page exists for now
// .when('/', { templateurl: 'Index.html', controller: 'Regioncontroller' })
// //todo: can able to add more pages using by specifying the condition in when clause
//});
var RegionController = function ($scope, $http) {
$scope.title = "Acturial App";
//$scope.data = [{
// "name": "Billings",
// "values": ['300031', '300051', '300091', '300111', '300131']
//}];
var regionDetails = [
{
"date": "6/30/2022",
"regionOffice": [
{
"name": "Valdosta",
"values": [
"300031",
"300051",
"300091",
"300111",
"300131"
]
},
{
"name": "Jackson",
"values": [
"300031",
"300051",
"300091",
"300111",
"300131"
]
},
{
"name": "Springfield",
"values": [
"300031",
"300051",
"300091",
"300111",
"300131"
]
},
{
"name": "Billings",
"values": [
"300031",
"300051",
"300091",
"300111",
"300131"
]
}
]
},
{
"date": "7/30/2023",
"regionOffice": [
{
"name": "Springfield",
"values": [
"300031",
"300051",
"300091",
"300111",
"300131"
]
},
{
"name": "Billings",
"values": [
"300031",
"300051",
"300091",
"300111",
"300131"
]
}
]
}
];
$scope.dataArray = regionDetails;
//var billingDetails = {
// name: 'Billings',
// values: ['300031', '300051', '300091', '300111', '300131']
//}
//$scope.data = billingDetails;
// TODO:Still have to make some improvements for the below functions
// The below code will be used when we have WebAPI endpoint so we can use that to populate the data
// instead of the static/hard-coded data
//var onUserComplete = function (response) {
// $scope.data = response.data;
// $http.get($scope.regionUrl)
// .then(onRepos, onError);
//}
//onRepos = function (response) {
// $scope.data = response.data;
//};
//var onError = function (response) {
// $scope.error = "Couldn't able to retreive the data";
//}
$scope.expandedRegion = null;
$scope.manageCollapseExpand = function (obj, isExpandedRegion) {
obj.expanded = !obj.expanded;
if (obj.expanded) {
if (!isExpandedRegion) {
$scope.expandedRegion = obj;
}
}
}
};
app.controller("RegionController", ["$scope", "$uibModal", "$http", RegionController]);
Here is the HTML Page
<!DOCTYPE html>
<html ng-app="acturial" ng-controller="RegionController">
<head>
<meta charset="utf-8" />
<title>{{title}}</title>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.4.7/angular-animate.js"></script>
<script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.14.3.js"></script>
<script src="Scripts/angular.js"></script>
<script src="acturial.js"></script>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular-route.js"></script>
<link data-require="bootstrap-css#*" data-semver="4.0.0-alpha.4" rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-alpha.4/css/bootstrap.min.css" />
<link data-require="font-awesome#*" data-semver="4.5.0" rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.css" />
<link href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div class="">
<label>
Filing Date:
</label>
<select ng-model="data.date" ng-options="data.date for data in dataArray" >
<option value=""> </option>
</select>
<br />
</div>
<div class="">
<button class="btn" ng-click="manageCollapseExpand(region, false)">
<span ng-class="{'glyphicon glyphicon-minus': region.expanded, 'glyphicon glyphicon-plus': !region.expanded }"></span>
</button>
{{region.name}} ({{region.values.length}})
</div>
<div class="" ng-show="region.expanded">
<div class="" ng-repeat="value in region.values">
<div class="">
{{value}}
</div>
</div>
</div>
</body>
</html>
So can you please help me with binding the data associated with the drop-down selected value and display below?
And below is the structured array I am seeing in the Console
We'll set up the data like this because ng-options (and choosing a default pre-selected option) requires binding to the same object. On the same object, we'll bind the chosen date, and the full array. Plus we need a variable for the index, which will be used to associate the office list with a particular date.
$scope.selectedDateIndex= null
$scope.ds = {};
$scope.ds.dataArray = regionDetails;
$scope.ds.date = $scope.ds.dataArray[0].date // this is our default pre-selected date
$scope.onSelectDate() // this will trigger showing the default date's office list
// this function will take the date that is chosen, find the data set in the array that matches, and set the `$scope.selectedDateIndex` we'll need
$scope.onSelectDate = function () {
let date = $scope.ds.date;
console.log(date)
$scope.ds.dataArray.forEach((el, index) => {
if (el.date == date) $scope.selectedDateIndex = index
})
}
For the <select>, set up an ng-change method. Also, notice the ng-model points at the object we set up before, and ng-options has this format optionValue as optionName forEach item in dataArray. For this to work, angular has to associate both option name and value.
<select ng-model="ds.date"
ng-options="data.date as data.date for data in ds.dataArray"
ng-change="onSelectDate()">
</select>
Then, here you had 2 outer divs, both using the region object which was wrong. I combined them. Your toggle button shouldn't call an outside function - just set region.expanded = !region.expanded. That way we keep it inside the object region which only exists in this loop.
<div class=""
ng-if="selectedDateIndex !== null"
ng-repeat="region in ds.dataArray[selectedDateIndex].regionOffice">
<!-- for the rest of this loop we can work with the `region` object -->
<button class="btn" ng-click="region.expanded = !region.expanded">
<span
ng-class="{'glyphicon glyphicon-minus': region.expanded, 'glyphicon glyphicon-plus': !region.expanded }"></span>
</button>
{{region.name}} ({{region.values.length}})
<div class="" ng-show="region.expanded">
<div class=""
ng-repeat="value in region.values">
<div class="">
{{value}}
</div>
</div>
</div>
</div>
I can't test this, so if you run into an error, let me know.

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

Display radio button data from array value in scope angular

I have web service call. I am getting response from webservice like this :
var SSOUserResponse = [
{
"UserName": "se",
"FirstAndLastName": "Sam ",
"EmailAddress": "segfgf#x.net"
},
{
"UserName": "se2",
"FirstAndLastName": "Joe ", //
"EmailAddress": "se266#gmail.com" //
}
];
or
SSOUserResponse array length can me more also.
$scope.launchArray = [];
I want to display this data in my templete.
What I am doing :
if (SSOUserResponse.length > 1) {
var launchArrayVal = [];
for (var i = 0; i < SSOUserResponse.length;i++){
launchArrayVal.push(
{ name: SSOUserResponse[i].UserName, email: SSOUserResponse[i].EmailAddress }
);
$scope.launchArray = launchArrayVal;
}
}
I have a templete :
<div class="modal-body">
<div>Please select an one data</div>
<div>
<input type="radio" ng-model="launchArray" name="group1" value="{{launchArray.name}}">
</div>
</div>
I want to display radio button with with username and email to display..
I tried ng-repeat also. It is not working.
Can u guide me what I doing wrong or what I can do?
Checkout this
<div class="modal-body">
<div>Please select an one data</div>
<div ng-repeat = 'item in launchArray'>
<input type="radio" ng-model="selected.value" name="group" ng-value="item.name">
<div> Name : {{item.name}}</div>
<div> Email : {{item.email}}</div>
</div>
</div>
<br>
<br>
<br>
<br>
<div >
<b>Selected Value :: </b>{{selected.value}}
</div>
var SSOUserResponse = [
{
"UserName": "se",
"FirstAndLastName": "Sam ",
"EmailAddress": "segfgf#x.net"
},
{
"UserName": "se2",
"FirstAndLastName": "Joe ", //
"EmailAddress": "se266#gmail.com" //
}
];
if (SSOUserResponse.length > 1) {
var launchArrayVal = [];
for (var i = 0; i < SSOUserResponse.length;i++){
launchArrayVal.push(
{ name: SSOUserResponse[i].UserName, email: SSOUserResponse[i].EmailAddress }
);
}
$scope.launchArray = launchArrayVal;
$scope.selected = {value: null};
}
You want to show one radio button per result, right?
This is when you would use ng-repeat. You didn't mention what the problem was when you used ng-repeat.
Currently, in your template, you're doing {{launchArray.name}} which won't work, since launchArray is an array... it doesn't have a name property.
Using ng-repeat, you loop over each item in launchArray and render a radio button each time:
<div class="modal-body">
<div>Please select an one data</div>
<div ng-repeat="item in launchArray">
<input type="radio" name="group1" value="{{item.name}}">
<span>{{item.name}} ({{item.email}})</span>
</div>
</div>

KnockoutJS not binding

I cant seem to get the binding to work on my KnockoutJS app.
JSFIDDLE -> http://jsfiddle.net/maylortaylor/pfqnkj17/
Here is the format of my JSON (generated by using <pre data-bind="text: ko.toJSON($root.forms,null,2)"></pre>)
[
{
"formTitle": "formTitle",
"formDescription": "formDesc",
"fieldTemplates": [
{
"fieldId": "text1",
"title": "title",
"description": "description fieldTemplate",
"isReq": true
},
{
"fieldId": "text2",
"title": "ttitle22",
"description": "description fieldTemplate 2",
"isReq": false
}
]
}
]
And here is how i am trying to call it in the page
<div id="MiddleColumn">
<input data-bind="textInput: $root.formTitle" type="text" placeholder="Title" class="span8 hideOffFocus input-full large-type">
<input data-bind="textInput: formDescription" type="text" placeholder="Description" class="hideOffFocus input-full">
</div
neither of those bindings work.
I create the forms object here
var FormModel = function (forms) {
var self = this;
self.forms = ko.observableArray(ko.utils.arrayMap(forms, function (form) {
return {
formTitle: form.formTitle, formDescription: form.formDescription,
fieldTemplates: ko.observableArray(form.fieldTemplates) };
}));
};
ko.applyBindings(new FormModel(initialData));
i hope your are expecting something like this
Working fiddle here
Now if you change something in textboxes in preview you can see automatic updates i.e mapping does make things back to ko way .
View Model :
var mapping = {
'fieldTemplates': {
create: function (options) {
return new FormModel(options.data);
}
}
}
function FormModel(forms) {
var self = this;
self.forms = ko.observableArray();
ko.mapping.fromJS(forms, mapping, self);
// other stuff
}
View :
<div id="MiddleColumn">
<input data-bind="textInput: $root.formTitle" type="text" />
<input data-bind="textInput: $root.formDescription" type="text"/><br/>
<div data-bind="foreach:$root.fieldTemplates">
<span data-bind="text:fieldId"></span>
<span data-bind="text:title"></span>
<span data-bind="text:description"></span>
<span data-bind="text:isReq"></span>
<br/>
</div>
</div>

How to properly execute a function inside ng-repeat

SITUATION:
I am making an app in AngularJs that assign permissions.
In order to do this i have three nested ng-repeat.
First loop: display PERMISSION GROUP
Second loop: For each permission group display CATEGORIES.
Inside this loop execute a function that will get all the SUB CATEGORIES for each category
Third loop: display SUB CATEGORIES
ISSUE:
The problem is in the execution of the function inside the second loop.
ATTEMPT 1 - ng-init:
<div class="row" ng-repeat="permission_group in list_permission_groups">
<div class="col-sm-3">
<h3>
{{permission_group.permission_group_name}}
</h3>
</div>
<div class="col-sm-9">
<ul>
<li ng-repeat="category in list_categories">
<span>
{{ category.name }}
</span>
<div class="checkbox">
<label>
<div ng-init="temp_result = get_Sub_Categories(category.category_id)">
<p ng-repeat="sub_category in temp_result">
{{ sub_category.name }}
</p>
</div>
</label>
</div>
</li>
</ul>
</div>
</div>
In the controller:
$scope.get_Sub_Categories = function(category_id) {
$http({
url: base_url + 'main/json_get_list_sub_categories',
data: {
category_id: category_id
},
method: "POST"
}).success(function(data) {
return data;
});
}
Te behavior is quite strange. Porbably due to dirty checking the page is loaded 682 times.
No result is displayed.
ATTEMPT 2 - ng-click: (only for debug)
<div class="row" ng-repeat="permission_group in list_permission_groups">
<div class="col-sm-3">
<h3>
{{permission_group.permission_group_name}}
</h3>
</div>
<div class="col-sm-9">
<ul>
<li ng-repeat="category in list_categories">
<span>
{{ category.name }}
</span>
<div class="checkbox">
<label>
<button ng-click="get_Sub_Categories(category.category_id)">
GET SUB-CATEGORIES
</button>
{{ list_sub_categories }}
</label>
</div>
</li>
</ul>
</div>
</div>
In the controller:
$scope.get_Sub_Categories = function(category_id) {
$http({
url: base_url + 'main/json_get_list_sub_categories',
data: {
category_id: category_id
},
method: "POST"
}).success(function(data) {
$scope.list_sub_categories = data;
});
}
This time the page is loaded only once.
If I press the button the proper sub-categories are displayed BUT of course not only for the corresponding category but FOR ALL, because i am modifying the var in the global scope.
THE AIM:
What I want to obtain is simply displaying all the proper sub-categories for each category.
Without using a button, but simply see all the proper content as soon as the page load.
But i don't understand how can this be done properly in AngularJs.
THE QUESTION:
How can i properly execute a function inside a ng-repeat that return and display different data for each loop?
EDIT - DUMP OF EXAMPLE OF SUB-CATEGORIES FOR ONE CATEGORY:
[{
"sub_category_id": "1",
"name": "SUB_CATEGORY_1",
"category_id_parent": "1",
"status": "VISIBLE"
}, {
"sub_category_id": "2",
"name": "SUB_CATEGORY_2",
"category_id_parent": "1",
"status": "VISIBLE"
}, {
"sub_category_id": "3",
"name": "SUB_CATEGORY_3",
"category_id_parent": "1",
"status": "VISIBLE"
}, {
"sub_category_id": "4",
"name": "SUB_CATEGORY_4",
"category_id_parent": "1",
"status": "VISIBLE"
}]
Calling a function inside ng-repeat is same as normal one. Since you need to display the sub categories at the time of page loading its better to get these data beforehand.
Asynchronously loading sub categories will not fit into this scenario.
Here is a minimal snippet achieving this (JS Fiddle)
<div ng-app="app" ng-controller="ctrl">
<div ng-repeat="category in model.categories"> <span> Category: {{ category.name }} </span>
<p ng-repeat="subCategory in getSubCategories(category.Id)">{{ subCategory.name }}</p>
</div>
</div>
Controller
angular.module("app", [])
.controller('ctrl', ['$scope', function ($scope) {
$scope.model = {
categories: [{
"Id": 1,
name: '1'
}, {
"Id": 2,
name: '2'
}],
subCategories: [{
"parentId": 1,
name: 'a1'
}, {
"parentId": 1,
name: 'a2'
},
{
"parentId": 2,
name: 'a3'
}]
}
$scope.getSubCategories = function(parentId){
var result = [];
for(var i = 0 ; i < $scope.model.subCategories.length ; i++){
if(parentId === $scope.model.subCategories[i].parentId){
result.push($scope.model.subCategories[i]);
}
}
console.log(parentId)
return result;
}}])
The subcategory example did not work for my case and it took my code into an infinte loop for some reason. may be because i was using an accordion.
I achieved this function call inside ng-repeat by using ng-init
<td class="lectureClass" ng-repeat="s in sessions" ng-init='presenters=getPresenters(s.id)'>
{{s.name}}
<div class="presenterClass" ng-repeat="p in presenters">
{{p.name}}
</div>
</td>
The code on the controller side should look like below
$scope.getPresenters = function(id) {
return SessionPresenters.get({id: id});
};
While the API factory is as follows:
angular.module('tryme3App').factory('SessionPresenters', function ($resource, DateUtils) {
return $resource('api/session.Presenters/:id', {}, {
'query': { method: 'GET', isArray: true},
'get': {
method: 'GET', isArray: true
},
'update': { method:'PUT' }
});
});
I think that the good solution here is to use Angular Directive.
You can see an example of directive used in a ng-repeat here : Angular Directive Does Not Evaluate Inside ng-repeat
For more information on directives, you can check the official documentation : https://docs.angularjs.org/guide/directive
I would create a factory for category then move your get_sub_categories function into this new factory.

Categories

Resources