knockout js - Display selected nested checkboxes - arrays

I have some code that lists some categories and subcategories with checkboxes but i can not get it to show a which checkboxes have been checked in a nested ul. It does return the selected items but not in a ul list.
please could you show me how to display the selected categories and sub catagories in a nested ul. Thanks.
var ViewModel = function() {
var self = this;
self.selectedCategories = ko.observableArray();
self.selectedItems = ko.observableArray();
self.categories = ko.observableArray([
{ name: 'Hospitality', items: [ 'Bars', 'Caterers', 'Cafes', 'Food To Go', 'Pubs' ] },
{ name: 'Popup', items: [ 'Food Vans', 'Festivals', 'Markets', 'Beer Garden' ] }
]);
}
var viewModel = new ViewModel();
ko.applyBindings(viewModel);
<ul data-bind="foreach: { data: categories, as: 'category' }">
<li> <input type="checkbox" name="level-1" data-bind="checked: $root.selectedCategories, attr: {value: name}"><span data-bind="text: category.name"></span></input>
<ul data-bind="foreach: { data: items, as: 'item' }">
<li><input type="checkbox" name="level-2" data-bind="checked: $root.selectedItems, attr: {value: item}"><span data-bind="text: item"></span></input></li>
</ul>
</li>
</ul>
<div data-bind="text: selectedCategories"></div>
<div data-bind="text: selectedItems"></div>

I'd suggest to store whether a category is selected, and its selected items, in the categories own model. You can make a computed in your ViewModel to create an array with only selected categories. Here's an example:
var ViewModel = function() {
var self = this;
self.categories = ko.observableArray([{
name: 'Hospitality',
items: ['Bars', 'Caterers', 'Cafes', 'Food To Go', 'Pubs'],
selected: ko.observable(false),
selectedItems: ko.observableArray([])
}, {
name: 'Popup',
items: ['Food Vans', 'Festivals', 'Markets', 'Beer Garden'],
selected: ko.observable(false),
selectedItems: ko.observableArray([])
}]);
self.selectedCategories = ko.computed(function() {
return self.categories().filter(function(cat) {
return cat.selected()
});
});
}
var viewModel = new ViewModel();
ko.applyBindings(viewModel);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.2.0/knockout-min.js"></script>
<ul data-bind="foreach: { data: categories, as: 'category' }">
<li>
<input type="checkbox" name="level-1"
data-bind="checked: selected, value: name">
<span data-bind="text: name"></span>
<ul data-bind="foreach: { data: items, as: 'item' }">
<li>
<input type="checkbox" name="level-2"
data-bind="checked: category.selectedItems, value: item, enable: category.selected">
<span data-bind="text: item, style: { 'opacity' : (category.selected() ? 1 : 0.5)}"></span>
</li>
</ul>
</li>
</ul>
<h2>Selections</h2>
<ul data-bind="foreach: selectedCategories">
<li>
<div data-bind="text: name"></div>
<ul data-bind="foreach: selectedItems">
<li data-bind="text: $data"></li>
</ul>
</li>
</ul>
Note: You had some invalid HTML in your snippet: you can't put a <span> element in an <input> element.

Related

nya-bs-select with boolean ng-model

How do I get nya-bs-select to use a boolean value on the model?
This is in the view:
<ol id="submitted" class="nya-bs-select" ng-model="submitted" ng-true-value="true" ng-false-value="false">
<li class="nya-bs-option" value="true">
<a>Submitted</a>
</li>
<li class="nya-bs-option" value="false">
<a>Not Submitted</a>
</li>
</ol>
Here is the controller:
$scope.submitted=true;
// $scope.submitted="true";
Here is the full plunkr:
https://plnkr.co/edit/iMvRDEr6s9zT6C34gM1y?p=preview
The only way to achieve this is by using an object as option and not a value like in this demo plnkr:
View
<ol class="nya-bs-select" ng-model="myModel">
<li nya-bs-option="option in options">
<a>{{option.name}}</a>
</li>
</ol>
Application
var app = angular.module('plunkerApp', ['nya.bootstrap.select']);
app.controller('MainCtrl', function($scope) {
$scope.options = [
{
value: true,
name: 'TRUE SELECTED'
}, {
value: false,
name: 'FALSE SELECTED'
},
];
});

How to add value to object from another object by click in Angular

I'm trying to create shopping cart, when clicking on one of the products its add to shoping cart.
So, I build an Object that contains all products, and another array that
will contain all clicked item.
When I'm trying to add the value of correct selected item from the products object i'm getting undefined.
var app = angular.module('myApp',[]); app.controller("myCtrl",function ($scope) {
$scope.products =
[
{ name: 'Apple', price: 5, img: '/Apple.jpg' },
{ name: 'Banana', price: 3.7, img: '/Banana.jpg' },
{ name: 'Grapes', price: 10 , img:'/Grapes.jpg' }
];
$scope.addProduct= function () {
$scope.products.push({name:$scope.nameProduct, price:$scope.priceProduct, tmuna:$scope.imgProduct});
$scope.nameProduct = "";
$scope.priceProduct = "";
$scope.imgProduct = "";
};
$scope.cartList = [{ name: 'Apple'}];
$scope.addToCart = function () {
$scope.cartList.push({name:$scope.nameProduct});
$scope.nameProduct = "";
};
});
<div class="dropdown pull-right">
<button class="btn btn-default dropdown-toggle" type="button" id="menu1" data-toggle="dropdown">
Shopping Cart <span class="glyphicon glyphicon-shopping-cart"></span>
<span class="caret"></span></button>
<ul class="dropdown-menu" role="menu" aria-labelledby="menu1" ng-repeat="product in cartList">
<li role="presentation"><a role="menuitem" tabindex="-1" >{{product.name}}</a></li>
</ul>
</div>
<form >
<p>Product: <input type = "text" ng-model = "nameProduct"></p>
<p>Price: <input type = "number" ng-model = "priceProduct"></p>
<p>Image: <input type = "text" ng-model = "imgProduct"></p>
<input type = "submit" value = "Add" ng-click = "addProduct()">
</form>
</div>
<div class="product" ng-repeat="product in products">
<img ng-src="{{product.img}}" />
<div class="name">{{product.name}}</div>
<div class="price">${{product.price}}</div>
<p class="badge" ng-click="addToCart()">Add to<span class="glyphicon glyphicon-shopping-cart"></span></p>
</div>
When you're calling addToCart() the function uses what's on $scope.nameProduct, but that's an empty string. You cleared it on addProduct() function.
Pass the name of the product you're adding:
ng-click="addToCart(product.name)"
And change your function accordingly:
$scope.addToCart = function (productName) {
$scope.cartList.push({ name: productName });
};
You need to pass the product object in the addToCart function like this:
https://jsfiddle.net/Lyrjp92z/
JS
$scope.addToCart = function(product) {
$scope.cartList.push({
name: product.name
});
};
HTML
<p class="badge" ng-click="addToCart(product)">Add to<span class="glyphicon glyphicon-shopping-cart"></span></p>
Also note, that passing in the product object and not just the string will allow you to also pass in the price, which you can calculate a total from.

How to show object in array angular?

How to show comments in items?
This is where items save
$scope.items = [
{ 'item': 'one',
'comments':[{'comment':'comment'}]
},
{ 'item': 'two',},
{'item': 'three'}
];
<ul>
<li ng-repeat="ite in items">
{{ite.item}} {{ite.comments.length}}
<button ng click="remove($index)">Remove</button> <div ng-repeat="c in ite.comments">{{c.comment}}</div>
</li>
</ul>
http://plnkr.co/edit/19w1Q3XhoWQcpxm5SuxX?p=preview
You Just missed to add your comment Div in between the list tag. please update the code like above code. I have checked on Plunker.
<li ng-repeat="ite in items">
{{ite.item}} {{ite.comments.length}}
<button ng-click="remove($index)">Remove</button> <div ng-repeat="c in ite.comments">{{c.comment}}</div></li>

Conditional ngRepeat based on dropdown

I would like to display a list based on which item is selected in a dropdown.
When I use the code below, I'm getting this error:
TypeError: Cannot read property 'type' of undefined
Any suggestions on how to do this right?
HTML:
<select class="form-control" ng-model="editProject.project.type"
ng-options="project as project.type for project in editProject.options track by project.type">
</select>
<ul class="list-group">
<li class="list-group-item" ng-repeat="benefit in editProject.foods()">{{snack}}</li>
</ul>
Controller:
.controller('EditProjectCtrl', function () {
var editProject = this;
editProject.options = [
{'type': 'Fruits'},
{'type': 'Vegetables'},
{'type': 'Desserts'}
];
editProject.snacks = function() {
if(editProject.project.type == 'Fruits') {return [
'Grapes',
'Oranges',
'Apples',
]}
if(editProject.project.type == 'Vegetables') {return [
'Broccoli',
'Spinache',
'Kale',
]}
else {return [
'Cookies',
'Cake',
'Pie']}
};
You are almost there. There was a mismatch between the ng-model of the select element, and the conditions in the controller. I also replaced benefit in editProject.foods() with snack in editProject.snacks():
<select class="form-control" ng-model="editProject.project" ng-options="project as project.type for project in editProject.options track by project.type"></select>
<ul class="list-group">
<li class="list-group-item" ng-repeat="snack in editProject.snacks()">{{snack}}</li>
</ul>
Because editProject.project is not defined until you select a project, you have to initialize it in the controller:
editProject.project = {};
See fiddle

How to implement PhoneJS SlideOut with AngularJS?

I tried the following code:
var app = angular.module('app', ['ngRoute', 'dx'])
app.controller('IndexCtrl', function($scope){
var contacts = [
{ name: "Barbara J. Coggins", phone: "512-964-2757", email: "BarbaraJCoggins#rhyta.com", category: "Family" },
{ name: "Carol M. Das", phone: "360-684-1334", email: "CarolMDas#jourrapide.com", category: "Friends" },
{ name: "Janet R. Skinner", phone: "520-573-7903", email: "JanetRSkinner#jourrapide.com", category: "Work" }
];
$scope.slideOutOptions = {
dataSource: contacts,
itemTemplate: 'item',
menuItemTemlate: 'menuItem'
}
})
<!-- HTML -->
<div class="app-index" ng-controller="IndexCtrl">
<div dx-slideout="slideOutOptions">
<div data-options="dxTemplate: { name: 'item' }">
<h1 data-bind="text: category"></h1>
<p><b>Name:</b> <span data-bind="text: name"></span></p>
<p><b>Phone:</b> <span data-bind="text: phone"></span></p>
<p><b>e-mail:</b> <span data-bind="text: email"></span></p>
</div>
<div data-options="dxTemplate: { name: 'menuItem' }">
<b data-bind="text: name"></b>
</div>
</div>
</div>
AngularJS there is not enough documentation on the DevExpress site. there are only examples using Knockout. Checkout PhoneJS DXSlideOut Documentation
The problem is in the HTML templates. You should use Angular syntax there.
<div dx-slideout="slideOutOptions">
<div data-options="dxTemplate: { name: 'item' }">
<h1>{{category}}</h1>
<p><b>Name:</b> <span>{{name}}</span></p>
<p><b>Phone:</b> <span>{{phone}}</span></p>
<p><b>e-mail:</b> <span>{{email}}</span></p>
</div>
<div data-options="dxTemplate: { name: 'menuItem' }">
<b>{{name}}</b>
</div>
</div>
Checkout docs about Angular approach.

Resources