Binding dynamic checkbox in angular.js - javascript

I have a list of options pulled from the database via json based on product selection in angular.js
Here's a sample code:
<ion-checkbox ng-repeat="extra in extras" ng-model="order.extras" checklist-value="{{ extra.id }}"><strong>{{ extra.name }}</strong></ion-checkbox>
I want a user to be able to select multiple extras but can't seem to be able to bind these selections.

I think it could work with ng-model="order.extras[extra.id]" then you can track the checked extras in order.extras.
Please have a look at the demo below or at this jsfiddle.
angular.module('demoApp', ['ionic'])
.controller('mainController', mainController);
function mainController($scope) {
$scope.order = {};
$scope.extras = [
{
id: 0,
name: 'first'
},
{
id: 1,
name: 'second'
},
{
id: 2,
name: 'third'
}
]
}
<link href="https://cdnjs.cloudflare.com/ajax/libs/ionic/1.2.4/css/ionic.min.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ionic/1.2.4/js/ionic-angular.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/ionic/1.2.4/js/ionic.bundle.js"></script>
<div ng-app="demoApp" ng-controller="mainController">
<ion-content>
<ion-checkbox ng-repeat="extra in extras" ng-model="order.extras[extra.id]" checklist-value="{{ extra.id }}"><strong>{{ extra.name }}</strong></ion-checkbox>
current order: {{order}}
</ion-content>
</div>

Related

show only one column of data of 2D array of scope

I am making a very simple custom directive, which will show, one column of product details, that is present in scope, as 2D array. The custom directive, will have an attribute, that will pass, which column of array has to be shown . Please see following plnkr--
https://plnkr.co/edit/zVIRZ8ADdQB4X8dSFOaJ
From UI I am using this--
<show-products type="name"></show-products>
Currently all data of the array is showing. but i need to show only 1 column of data and that column will be mentioned by directive attribute(for example -name as in plnkr)
In link function I am able to get the column name by using following code-
link: function postlink(scope, element, attr) {
console.log("...type..." + attr["type"]); // prints name
}
but how to pass that field name to template?
template: '<div ng-repeat="x in products">{{x}}</div>' // i need to print only name column here
You get those attributes for the template function as well, just create a function instead of a string and pass your attribute type into the product type variable.
The documentation for the function version of the template can be found in the angular v1 documentation: https://docs.angularjs.org/guide/directive
For more see the snippet below.
<html ng-app="app">
<head>
<title>Directives</title>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.1/angular.js"></script>
<script>
angular.module("app", []);
angular.module("app")
.controller("ctrl", ctrl)
.directive("showProducts", showProducts);
function ctrl($scope) {
$scope.products = [{
name: "Apples",
category: "Fruit",
price: 1.20,
expiry: 10
}, {
name: "Bananas",
category: "Fruit",
price: 2.42,
expiry: 7
}, {
name: "Pears",
category: "Fruit",
price: 2.02,
expiry: 6
}];
};
function showProducts() {
return {
template: (child, attributes) => {
return `<div ng-repeat="x in products">{{x["${attributes["type"]}"]}}</div>`
}
};
};
</script>
</head>
<body>
<div class="panel panel-default">
<div class="panel-body" ng-controller="ctrl">
<show-products type="name"></show-products>
</div>
</div>
</body>
</html>

Angularjs - filter object by search value, but don't omit if the search value is in the second object

Having trouble even writing the subject with my lack of english.
So here I go, I have for example two objects connected by the colorid:
$scope.fruits = {{name:"apple",colorid:"1"},etc};
$scope.colors = {{id:"1",value:"red"};
I've built a nice table with search and filter, using ng-repeat
ng-repeat="fruit in fruits | orderBy:sortType:sortReverse | filter:search"
What I am trying to achieve is ... when i search/filter for "red", to still view "apple"..
Edit: Obviously there is no connection in the ng-repeat with the second object "colors", the simplest solution would be to iterate each "fruit" and .push its color value (red) in the "fruits" object itself, so when searched/filtered for "red", the "apple" object is still visible in the search table.
But I assumed there may be some "angular-ish" solution for connected tables and their relationship ids.
If I understood well you are trying to "connect" your arrays. So you can have nested ngRepeat, as below:
(function() {
"use strict";
angular
.module('app', [])
.controller('MainCtrl', MainCtrl);
MainCtrl.$inject = ['$scope'];
function MainCtrl($scope) {
$scope.fruits = [
{
"name":"apple",
"colorid":1
},
{
"name":"mango",
"colorid":2
},
{
"name":"papaya",
"colorid":3
}
];
$scope.colors = [
{
"id":"1",
"value":"red"
},
{
"id":2,
"value":"green"
},
{
"id":3,
"value":"yellow"
}
];
}
})();
<!DOCTYPE html>
<html ng-app="app">
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.min.css" />
</head>
<body ng-controller="MainCtrl">
<input type="text" class="form-control" ng-model="search" placeholder="Search...">
<ul ng-repeat="fruit in fruits track by $index">
<li ng-if="filtered.length" ng-bind="fruit.name"></li>
<ul>
<li ng-repeat="color in colors | filter: { id: fruit.colorid } | filter: search as filtered track by $index" ng-bind="color.value">
</li>
</ul>
</ul>
</body>
</html>

Unable to use inherited/isolated scope concept in my example plunker

I am learning inherited/isolated scopes in angular directives and struck with some basic concepts. please see the plunker below.
Example.
Scenario1:
I have 2 directives (book and details). I am displaying two "Book Details" containers and toggling book name by sending custom attributes like this.
<book bookdetails="book" collapsed="yes" list="list"></book>
<book bookdetails="book1" collapsed="no" list="list"></book>
Question: Is this the right way to handle displaying things in 2 different containers?
Scenario 2:
I want to hide the author details section in container 1 but show in container2 on load. How to accomplish that?
When I use this line below it will hide and show both author details section but I want to keep it separate.
<details collapsed="yes"></details>
I know I am lacking basic skills using inherited/isolated scopes. Can someone educate me?
It's OK to use nested directives like you've used so you can do everything related to the details pane in the details controller like removing items from the books list.
If you wouldn't do any logic in details controller and just include some html I would just use ng-include.
Some points I've detected during improving your code:
Template markups are partial html files, so no need to add header, body etc. Just add your markup that you need in your directive.
I've created one model array books that you can iterate with ng-repeat and not two separate scope variables. That's easier to add more books.
I wouldn't pass the collapsed state to directive isolated scope. I would add it to the book model then you can have independent states of the details panes.
You could also create a collapsed array scope variable separate from your model and use it like ng-hide='collapsed[$index]' if you don't like to add it to your model.
Don't compare to the string yes. It makes things more complicated. It's better to use true or false.
The list you're passing is OK if you'd like to use one list for every details pane. But I think you need them independent from each other so add it to your book model.
For toggeling a value you can use the js shorthand: collapsed = !collapsed;. It takes the value of collapsed and inverts it and re-asigns it to collapsed.
Details directive: You don't need to pass attributes to a directive that doesn't use isolated scope. Instead you can directly use the inherited scope of the parent.
Note: I think you should have a look at angular-ui-bootstrap and use an accordion instead of your manually created panes later. But for learning directives your code is OK.
Please have a look at your updated code below or in this plunker.
If something is not clear, feel free to add a comment and I'll try to help.
angular.module('plunker', [])
.controller('MainCtrl', function($scope) {
$scope.books = [{
id: 0,
name: 'Building modern ASP.NET 5',
author: {
name: 'name1',
age: 31,
country: 'USA'
},
collapsed: false,
list: [{
id: 0,
name: 'book1'
}, {
id: 1,
name: 'book2'
}, {
id: 2,
name: 'book3'
}]
}, {
id: 1,
name: 'AngularJS',
author: {
name: 'name2',
age: 27,
country: 'USA'
},
collapsed: true,
list: [{
id: 0,
name: 'book1'
}, {
id: 1,
name: 'book2'
}, {
id: 2,
name: 'book3'
}]
}];
//$scope.list = ["book1", "book2", "book3"];
}).directive('book', function() {
return {
restrict: 'E',
templateUrl: 'book.html',
scope: {
bkdet: "=bookdetails"
//list: "="
//collapsed: "#"
},
controller: function($scope) {
$scope.toggleDetails = function() {
$scope.bkdet.collapsed = !$scope.bkdet.collapsed;
updateCaption();
};
function updateCaption() {
$scope.hypshowhide = $scope.bkdet.collapsed ? 'show details' : 'hide details';
}
// first run
updateCaption();
/*if ($scope.collapsed == 'yes')
{
$scope.dethide = true;
}
else {
$scope.dethide = false;
} */
//$scope.hypshowhide = 'show details';
}
}
})
.directive('details', function() {
return {
restrict: 'E',
templateUrl: 'details.html',
controller: function($scope) {
/*console.log($scope.bkdet.collapsed);
if (!$scope.bkdet.collapsed) { //== 'yes') {
$scope.dethide = true;
}
else {
$scope.dethide = false;
}*/
$scope.removeItem = function(index) {
$scope.bkdet.list.splice(index, 1);
}
}
}
})
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="plunker">
<div ng-controller="MainCtrl">
<div class="container">
<book bookdetails="book" ng-repeat="book in books"></book>
</div>
</div>
<script type="text/ng-template" id="book.html">
<div class="row">
<div class="panel panel-default">
<div class="panel-heading">
<h1>Book Details</h1>
</div>
<div class="panel-body">
<a class="pull-right" href="#" ng-click="toggleDetails(collapsed)">{{hypshowhide}}</a>
<div>
<!--ng-hide="dethide">-->
{{bkdet.name}}
</div>
<!--<details collapsed="no"></details>-->
<details></details>
</div>
</div>
</div>
</script>
<script type="text/ng-template" id="details.html">
<div class="container" ng-hide="bkdet.collapsed">
<div class="row">
<ul class="list-group list-unstyled">
<!--<li>
<h1>Author:</h1>
</li>
<li>
<ul>-->
<li>
<strong>Author</strong>
{{bkdet.author.name}}
</li>
<li>
<strong>Age</strong>
{{bkdet.author.age}}
</li>
<li>
<strong>Country</strong>
{{bkdet.author.country}}
</li>
<li>
<div ng-if="bkdet.list.length == 0">
<p>No books here!</p>
</div>
<div ng-repeat="c in bkdet.list">
<p>
{{c.name}}
<button class="btn btn-danger" ng-click="removeItem($index)">X</button>
</p>
</div>
</li>
<!--</ul>
</li>-->
</ul>
</div>
</div>
</script>
</div>

Unable to get the selection when using angular-winjs ListView

I'm using angular-winjs to display a list. The HTML as well as the controller code is below. When I click the item, the selection is not set. As a result, the watch never gets called.
How can I get the selected item in the selection variable? My code looks similar to this issue, but have the problem still. I'm using the latest WinJS.
<div ng-app="myApp">
<div ng-controller="HomeTilesController">
<div>Selected count: {{selection.length}}, indexes: {{selection}}</div>
<win-list-view item-data-source="homeTiles" selection-mode="'single'" selection="selection">
<win-item-template>
<div class="tile">
<h5 class="win-h5">{{item.data.title}}</</h5>
</div>
</win-item-template>
<win-grid-layout></win-grid-layout>
</win-list-view>
</div>
</div>
HomeTilesController:
angular.module('myApp', ['winjs'])
.controller("HomeTilesController", ['$scope', function ($scope) {
$scope.homeTiles = [
{ title: 'Agents' },
{ title: 'Center' },
{ title: '' },
{ title: '' },
{ title: '' },
{ title: '' }];
$scope.selection = [1];
$scope.$watch('selection', function handleSelectionChange(newValue, oldValue) {
console.log('item selected');
})
}]);
The tiles are displayed correctly as below. You may notice that the Center tile (tile with the blue border) that has been selected as a result of setting the selection. But any other selection still shows the same value - selecting any other item wont set the selection.
The libraries are below:
<script src="~/lib/jquery/dist/jquery.js"></script>
<script src="https://cdn.rawgit.com/twbs/bootstrap/v4-dev/dist/js/bootstrap.js"></script>
<script src="~/lib/hammer.js/hammer.js"></script>
<script src="https://code.angularjs.org/tools/system.js"></script>
<script src="https://code.angularjs.org/tools/typescript.js"></script>
<script src="~/lib/angular/angular.min.js"></script>
<script src="https://code.angularjs.org/2.0.0-alpha.44/angular2.dev.js"></script>
<link href="https://cdnjs.cloudflare.com/ajax/libs/winjs/4.4.0/css/ui-light.css" rel="stylesheet" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/winjs/4.4.0/js/base.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/winjs/4.4.0/js/ui.js"></script>
<script src="https://cdn.rawgit.com/winjs/angular-winjs/master/js/angular-winjs.js"></script>
<script src="~/app/my-app.js"></script>
<link href='https://fonts.googleapis.com/css?family=Roboto' rel='stylesheet' type='text/css'>
<script src="~/js/site.js" asp-append-version="true"></script>
You have to use selection-mode="'single'" tap-behavior="'directSelect'"
var myApp = angular.module("myApp", ['winjs']);
myApp.controller("myCtrl", ['$scope', myCtrl]);
function myCtrl($scope) {
$scope.selection = [];
$scope.homeTiles = [{
title: 'A1'
}, {
title: 'A2'
}, {
title: 'A3'
}, {
title: 'A4'
}, {
title: 'A5'
}, {
title: 'A6'
}];
}
HTML
<div ng-app="myApp">
<div ng-controller="myCtrl">
<div>Selected count: {{selection.length}}, indexes: {{selection.toString()}}</div>
<win-list-view item-data-source="homeTiles" selection="selection" selection-mode="'single'" tap-behavior="'directSelect'" class="listview win-selectionstylefilled">
<win-item-template>This list view item's rating is: {{item.data.rating}}</win-item-template>
<win-list-layout></win-list-layout>
</win-list-view>
</div>
</div>
Working code JSFiddle
WinJS ListView Interaction Examples ( Choose from dropdown )

Angularjs combo box key value

I am using Angularjs and I have a dropdown box that lists several items. If the item the user needs is not in the list I need to allow the user to enter the data. Is this possible? How would I do it?
Try this out
Working Demo
html
<div ng-app="myapp">
<fieldset ng-controller="FirstCtrl">
<select ng-options="p.name for p in people" ng-model="selectedPerson"></select>
<br>
Name:<input type="text" ng-model="name"/>
<button ng-click="add(name)">Add</button>
</fieldset>
</div>
script
var myapp = angular.module('myapp', []);
myapp.controller('FirstCtrl', function ($scope) {
$scope.people = [{
name: 'John'
}, {
name: 'Rocky'
}, {
name: 'John'
}, {
name: 'Ben'
}];
$scope.add = function(value)
{
var obj= {};
obj.name = value;
$scope.people.push(obj);
$scope.name = '';
}
});
You seem to want something like a tagging widget. Maybe looking at angular-tags you can accomplish what you want

Categories