How to create json object in Angularjs - javascript

i want to create json object in Angularjs. when add on addBasket add new basket object to array and when click on addOrder add new order to array. in fact date field not repeat in loop. dothis way is good to create json object? or may be exist good solution to create json object.
Edit question:
I would like to create object in the json format. I put the format below. I wrote the code that I've put it. In fact, my problem is to add an object to the orders array. how add new object to orders array?
[
{
"date":'2015-30-7',
"baskets": [
{
"orders": [
{
"id": "12"
}
],
"customer": {
"phone": "555555"
},
"discount": "8"
}
]
}
]
var app = angular.module('app', []);
app.controller('myController', function($scope, $http) {
$scope.typistData = [];
$scope.typistData.push({
baskets: [{
orders:[]
}]
});
$scope.addBasket = function() {
$scope.typistData.push({
baskets: [{
orders:[]
}]
});
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app='app' ng-controller='myController'>
<input type="text" ng-model="data.name">
<hr>
<div ng-repeat="data in typistData" ng-if="typistData">
<form novalidate ng-submit="submitOffices()">
<div>
<ng-form ng-repeat="basket in data.baskets">
<div>
<input type="text" ng-model="basket.customer.phone">
<br>
<input type="text" ng-model="basket.discount">
<input type="text" ng-model="basket.orders[0].id">
<input type="button" value="addOrder">
</div>
<hr>
</ng-form>
</div>
</form>
</div>
<button ng-click="addBasket()">Add Basket</button>
<div>
<pre>{{ typistData | json }}</pre>
</div>
</div>

From what I have understood from your question, you want to able to add a basket to the baskets of any of the typists, and also you want to add an order to the orders of one of the baskets of one of the typists.
For handling that I think you can pass in the right objects for addBasket and addOrder inside ng-repeat with ng-click (it works because it passes the reference). So a possible working change can be this :
View part :
<div ng-repeat="data in typistData" ng-if="typistData">
<form novalidate ng-submit="submitOffices()">
<div>
<ng-form ng-repeat="basket in data.baskets">
<div>
<input type="text" ng-model="basket.customer.phone">
<br>
<input type="text" ng-model="basket.discount">
<input type="text" ng-model="basket.orders[0].id">
<!-- Here you call the addOrder with basket. -->
<button ng-click="addOrder(basket)">Add Order</button>
</div>
<hr>
</ng-form>
<!-- Here you call the addBasket with data. .-->
<button ng-click="addBasket(data)">Add Basket</button>
</div>
</form>
</div>
Controller part :
var app = angular.module('app', []);
app.controller('myController', function($scope, $http) {
$scope.typistData = [];
$scope.typistData.push({
baskets: [{
orders:[]
}]
});
/* This is wrong, because it doesn't add a basket, instead it
another typist's details.
$scope.addBasket = function() {
$scope.typistData.push({
baskets: [{
orders:[]
}]
});
Correct way of adding it is to use the passed in reference to the
data of a particular typist, and add a basket to its baskets.
*/
$scope.addBasket = function(typist) {
// Adding a basket to the typist's baskets, and you want the
// basket to contain an empty orders array initially right.
typist.baskets.push({
orders:[]
});
};
// To add an order to one of the basket of the baskets of a
// particular typist.
$scope.addOrder = function(typistBasket) {
typistBasket.orders.push({
// Whatever you want the order to have.
});
};
});

Related

How do I use an attribute directive inside an element directive template in angularjs?

I have a need to show a list of check boxes on my site listing products and other items. The checklist-model attribute directive works well for this because I can bind it to a list of items that relates to the items selected.
All this works fine when I simply use this code in my angular controller. However, I have several list boxes that need to be displayed the same way with the same "select all" and "select none" buttons for each list. I don't want to repeat this code and layout so I've created my own directive for the entire list.
The problem is when I use my own directive it doesn't bind correctly back to my data, the select all only works once, and the select none doesn't work at all.
I suspect it has something to do with how I'm passing the scope around, and the two directives are not working well together.
Why does this not work inside a directive?
Here is a jsfiddle: https://jsfiddle.net/fande455/m9qhnr9c/7/
HTML
<section ng-app="myApp" ng-controller="couponEditController">
<script type="text/ng-template" id="checkboxlist.template.html">
<div>
<div class="form-input form-list">
<label ng-repeat="item in valuelist | orderBy:value">
<input type="checkbox" checklist-model="model" checklist-value="item" /> {{item[value]}}
<br />
</label>
</div>
<button class="btn btn-default" style="float:left; margin-bottom: 5px;margin-left: 10px;margin-right:10px" ng-click="selectNone()">Select None</button>
<button class="btn btn-default" style="float:left; margin-bottom: 5px;" ng-click="selectAll()">Select All</button>
<div class="cleared"></div>
</div>
</script>
<div>
<checkboxlist model="coupon.Products" value="Name" valuelist="productsList"></checkboxlist>
</div>
</section>
JS
var myApp = angular.module('myApp', ['checklist-model']);
myApp.directive('checkboxlist', [function() {
return {
restrict: 'E',
templateUrl: 'checkboxlist.template.html',
controller: 'checkboxlistController',
scope: {
model: "=",
value: "#",
valuelist: "="
},
require: '^checklist-model'
}
}]);
myApp.controller('checkboxlistController', ['$scope', function($scope) {
$scope.selectAll = function() {
$scope.model = angular.copy($scope.valuelist);
};
$scope.selectNone = function() {
$scope.model = [];
};
}]);
myApp.controller('couponEditController', ['$scope', function($scope) {
$scope.coupon =
{"Id": 1,
"Name": "My Coupon",
"Products": []
}
;
$scope.productsList = [{
"Id": 1,
"Name": "Product 1"
}, {
"Id": 2,
"Name": "Product 2"
}];
}]);
From documentation:
Instead of doing checklistModelList = [] it is better to do
checklistModelList.splice(0, checklistModelList.length)
In your code you should do
$scope.selectAll = function() {
$scope.selectNone();
$scope.model.push.apply($scope.model, $scope.valuelist);
};
$scope.selectNone = function() {
$scope.model.length = 0;
};
Here's the updated fiddle: https://jsfiddle.net/m9qhnr9c/9/
The idea is not to replace the array with a new one, but modify only its elements.

Show different buttons matching array values

So here's my problem, i'm using AngularJS and i'm getting JSON from PHP, and displaying all my data with ng-repeat. I already have done this.
Now I want to check if some data is in "Array1" and if it is, change the correspndent data from the ng-repeat. I know it sounds really weird, but let me put an example with code:
Here's array1 values
{
"23",
"48",
"51"
}
So when i get the data, it's something like this:
{
id : "23",
name: "example"
}
And for every JSON object i'm using ng-repeat to display them all like this:
<div ng-model="data.posts" ng-repeat="post in posts | orderBy:'-' | unique: 'id'">
...
<button>This button will show if "id" matches</button>
<button>This button will show if "id" not matches</button>
</div>
I want to compare if an id of array1 matches an id from the JSON data and if it matches show one button and if not show other.
I'm on this like 2 weeks, and i can't get the problem solved, and i don't see any way to get it.
Thx for reading at least and sorry for my bad english!
Your array1 should be an array and can add a function in controller to check match id.
in controller:
$scope.array1 = ["23","48","51"];
$scope.checkInArray1 = function(id) {
var index = $scope.array1.indexOf(id);
if(index < 0){
return false;
} else {
return true;
}
};
and in your html:
<button ng-if="checkInArray1(post.id)">This button will show if "id" matches</button><br>
<button ng-if="!checkInArray1(post.id)">This button will show if "id" not matches</button>
Making the assumption that {"23","48","51"} should be a array ["23","48","51"]
You could do something like this:
Working Fiddle: http://jsfiddle.net/ravenous52/rgyom4yd/
myApp.controller('MyCtrl', ['$scope',
function($scope) {
$scope.knownIds = ["23", "48", "51"];
$scope.data = {
posts: [{
id: "23",
name: "example23"
}, {
id: "51",
name: "example51"
}, {
id: "99",
name: "example99"
}]
}
}
]);
<section ng-controller="MyCtrl">
<div ng-repeat="post in data.posts">
<button ng-show="knownIds.indexOf(post.id) >-1">This button will show if "id" matches</button>
<button ng-hide="knownIds.indexOf(post.id) >-1">This button will show if "id" not matches</button>
</div>
</section>
https://jsfiddle.net/alair016/4wc44on1/
<div ng-app='myApp' ng-controller="MyCtrl">
<div ng-model="data.posts" ng-repeat="post in data.posts">
<button ng-if="array1.indexOf(post.id) >-1">{{post.name}} id matches</button>
<button ng-if="array1.indexOf(post.id) == -1">{{post.name}} id does not match</button>
</div>
</div>
var myApp = angular.module('myApp',[])
.controller('MyCtrl', ['$scope', function($scope) {
$scope.array1 = ["23","48","51"];
$scope.data = {
posts : [
{
id : "23",
name: "example"
},
{
id: "24",
name:"second example"
}
]
};
}]);

Angular JS, put json to ng-repeat out of an event fails

I am new to Angular and I have this issue that I don't get solved. I have read today alot about good style and $scope soup but I could not find an answer to this.
It is the following, very easy example:
I have a controller with an ng-repeat inside and an input with a change-event.
<div id="searchbar" data-ng-controller="SearchCtrl">
<input id="search" autocomplete="off" data-ng-model="search" data-ng-keyup="getResults( search );" />
<div id="input_results">
<li data-ng-repeat="x in names">
{{ x.Country }}
</li>
</div>
</div>
When I assign some json directly from the controller function everything works fine.
var app = angular.module("myApp", []);
var SearchCtrl = function($scope, $http, HTTPService) {
console.log("Control opened");
$scope.names = [{
"Country": "TEXT"
}];
};
When I try to assign json out of the event, then I receive there "parent is null"
var app = angular.module("myApp", []);
var SearchCtrl = function($scope, $http, HTTPService) {
var _this = this;
console.log("Control opened");
$scope.getResults = function(searchstring) {
console.log("Execute search: " + searchstring);
$scope.names = [{
"Country": "TEXT"
}];
_this.getResults(searchstring, $scope, $http);
};
};
I don't know how I can pass the correct scope to getResults() or how to solve this issue. Additionally I have read that it is best to use dots in model names like SearchStrl.search to avoid shadowing.
I am also confused about the behaviour, when I change $scope.search it works fine inside the getResult() function, but why not with the ng-repeat.
It would be nice if somebody could explain me the reason for this behaviour.
Thank you.
Your ng-repeat code fails to work because he doesn't has an array to repeat on through.the code only creates the array after you activated 'getResults' function.
in your controller you shold have something like this:
app.controller('CTRL1', function($scope){
$scope.names = [{
"Country": "TEXT"
}]; //your array
$scope.getResults = function(search) {
//your search code.
}
})
I can see you're trying to make a list of items with a search. instead of the above code I will suggest you do as followed:
<div data-ng-controller="SearchCtrl">
<input data-ng-model="search" /> <!-- creates a search instance- -->
<div id="input_results">
<!--filter by search model -->
<li data-ng-repeat="x in names | filter: search">
{{ x.Country }}
</li>
</div>
and in your code:
$scope.names = [{
"Country": "TEXT"
}];

Angular validate form with dynamic name

Typically to validate a form in Angular, I would use something like this on the ng-submit directive:
<form name="formName" ng-submit="formName.$valid && submitForm()"></form>
This works great when the form has a name that I set myself while building the form. However, in my current situation, I am trying to create multiple forms based on a list of objects. In this case, each form has a name that is determined on the fly.
When the user submits one of these forms, how can I validate it before running the submitForm() function for that form?
Here's a jsfiddle of the simplified problem: http://jsfiddle.net/flyingL123/ub6wLewc/1/
My question is, how can I access the name of the form in order to validate it? Here is the code from the fiddle:
var app = angular.module('app', []);
app.controller("AppController", ['$scope', function($scope) {
$scope.forms = [{
id: 1,
value: "val1"
}, {
id: 2,
value: "val2"
}, {
id: 3,
value: "val3"
}];
$scope.submitForm = function() {
alert('submitted');
}
}]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.1/angular.min.js"></script>
<div id="app" ng-app="app" ng-controller="AppController">
<div class="formWrapper" ng-repeat="form in forms">
<form name="{{ 'form' + form.id }}" ng-submit="submitForm()" novalidate>
<input ng-model="form.value" required />
<button type="submit">Submit</button>
</form>
</div>
</div>
You can always use this to access the scope in your templates.
{{this.foo === foo}} <!-- This will always show "true" -->
Therefore, you can simply use this[myDynamicFormName] to access the form:
<form name="{{'form' + form.id}}" ng-submit="this['form' + form.id].$valid && submitForm()"></form>

AngularJS group check box validation

I have a list of check boxes, of which at least one is compulsory. I have tried to achieve this via AngularJS validation, but had a hard time. Below is my code:
// Code goes here for js
var app = angular.module('App', []);
function Ctrl($scope) {
$scope.formData = {};
$scope.formData.selectedGender = '';
$scope.gender = [{
'name': 'Male',
'id': 1
}, {
'name': 'Female',
'id': 2
}];
$scope.formData.selectedFruits = {};
$scope.fruits = [{
'name': 'Apple',
'id': 1
}, {
'name': 'Orange',
'id': 2
}, {
'name': 'Banana',
'id': 3
}, {
'name': 'Mango',
'id': 4
}, ];
$scope.submitForm = function() {
}
}
// Code goes here for html
<!doctype html>
<html ng-app="App">
<head>
<!-- css file -->
<!--App file -->
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.8/angular.js"></script>
<!-- External file -->
</head>
<body>
<div ng-controller="Ctrl">
<form class="Scroller-Container">
<div ng-app>
<form class="Scroller-Container" ng-submit="submit()" ng-controller="Ctrl">
<div>
What would you like?
<div ng-repeat="(key, val) in fruits">
<input type="checkbox" ng-model="formData.selectedFruits[val.id]" name="group[]" id="group[{{val.id}}]" required />{{val.name}}
</div>
<br />
<div ng-repeat="(key, val) in gender">
<input type="radio" ng-model="$parent.formData.selectedGender" name="formData.selectedGender" id="{{val.id}}" value="{{val.id}}" required />{{val.name}}
</div>
<br />
</div>
<pre>{{formData.selectedFruits}}</pre>
<input type="submit" id="submit" value="Submit" />
</form>
</div>
<br>
</form>
</div>
</body>
</html>
Here is the code in plunker: http://plnkr.co/edit/Bz9yhSoPYUNzFDpfASwt?p=preview Has anyone done this on AngularJS? Making the checkboxes required, forces me to select all the checkbox values. This problem is also not documented in the AngularJS documentation.
If you want to require at least one item in group being selected, it's possible to define dynamic required attribute with ng-required.
For gender radio buttons this would be easy:
<input
type="radio"
ng-model="formData.selectedGender"
value="{{val.id}}"
ng-required="!formData.selectedGender"
>
Checkbox group would be easy too, if you used array to store selected fruits (just check array length), but with object it's necessary to check if any of values are set to true with filter or function in controller:
$scope.someSelected = function (object) {
return Object.keys(object).some(function (key) {
return object[key];
});
}
<input
type="checkbox"
value="{{val.id}}"
ng-model="formData.selectedFruits[val.id]"
ng-required="!someSelected(formData.selectedFruits)"
>
Update:
const someSelected = (object = {}) => Object.keys(object).some(key => object[key])
Also keep in mind that it will return false if value is 0.
Thanks to Klaster_1 for the accepted answer. I've built on this by using ng-change on the checkbox inputs to set a local scope variable, which would be used as the ng-required expression. This prevents the running of someSelected() on every digest.
Here is a plunkr demonstrating this: http://embed.plnkr.co/ScqA4aqno5XFSp9n3q6d/
Here is the HTML and JS for posterity.
<!DOCTYPE html>
<html ng-app="App">
<head>
<meta charset="utf-8" />
<script data-require="angular.js#1.4.9" data-semver="1.4.9" src="https://code.angularjs.org/1.4.9/angular.js"></script>
<script src="script.js"></script>
</head>
<body>
<div ng-controller="AppCtrl">
<form class="Scroller-Container" name="multipleCheckbox" novalidate="">
<h3>What would you like?</h3>
<div ng-repeat="fruit in fruits">
<input type="checkbox" ng-model="formData.selectedFruits[fruit.name]" ng-change="checkboxChanged()" ng-required="!someSelected" /> {{fruit.name}}
</div>
<p style="color: red;" ng-show="multipleCheckbox.$error.required">You must choose one fruit</p>
</form>
<pre>Fruits model:
{{formData.selectedFruits | json}}</pre>
</div>
</body>
</html>
angular
.module('App', [])
.controller('AppCtrl', function($scope) {
var selectedFruits = {
Mango: true
};
var calculateSomeSelected = function() {
$scope.someSelected = Object.keys(selectedFruits).some(function(key) {
return selectedFruits[key];
});
};
$scope.formData = {
selectedFruits: selectedFruits
};
$scope.fruits = [{
'name': 'Apple'
}, {
'name': 'Orange'
}, {
'name': 'Banana'
}, {
'name': 'Mango'
}];
$scope.checkboxChanged = calculateSomeSelected;
calculateSomeSelected();
});
Okay maybe very late to the party but if you have an array of objects which you are looking at, the solution of just checking the length of array of selected objects worked for me.
HTML
<div ng-repeat="vehicle in vehicles">
<input type="checkbox" name="car" ng-model="car.ids[vehicle._id]" ng-required=" car.objects.length <= 0"> {{vehicle.model}} {{vehicle.brand}} <b>{{vehicle.geofenceName}}</b>
</div>
JS
$scope.vehicles = [{},{}] // Your array of objects;
$scope.car = {
ids: {},
objects: []
};
$scope.$watch(function() {
return $scope.car.ids;
}, function(value) {
$scope.car.objects = [];
angular.forEach($scope.car.ids, function(value, key) {
value && $scope.car.objects.push(getCategoryById(key));
});
}, true);
function getCategoryById(id) {
for (var i = 0; i < $scope.vehicles.length; i++) {
if ($scope.vehicles[i]._id == id) {
return $scope.vehicles[i];
}
}
}
I understand what is happening in this solution that you are checking all the checkbox options to know which one is clicked. But from what I know this is by far the easiest solution(to understand and implement) and it works like a charm if you know that your options will be limited.
For a more time optimized solution. Check the answers above.
We can achieve your requirement without traversing all check-boxes instance.
Here is the sample code
<script>
angular.module('atLeastOneExample', [])
.controller('ExampleController', ['$scope', function($scope) {
$scope.e = function(s){
eval(s);
};
}]);
</script>
Here i am wrapping javascript eval function in "e" function to access it.
<form name="myForm" ng-controller="ExampleController" ng-init="c=0">
<label>
Value1: <input type="checkbox" ng-model="checkboxModel.value[0]" ng-change="e('($scope.checkboxModel.value[0])?$scope.c++:$scope.c--')"/>
</label><br/>
<label>
Value2: <input type="checkbox" ng-model="checkboxModel.value[1]" ng-change="e('($scope.checkboxModel.value[1])?$scope.c++:$scope.c--')"/>
</label><br/>
value = {{checkboxModel.value}}<br/>
isAtLeastOneChecked = {{c>0}}
</form>

Categories