AngularJS radio buttons ng-repeat value - javascript

I'm creating radio buttons with ng-repeat and would like the selected button's name value to appear below.
Here is my view:
<span ng-repeat="weight in weights">
<input type="radio" name="weight" value="{{weight.name}}" id="weight{{weight.name}}" ng-checked="weight.checked">
<label for="weight{{weight.name}}">{{weight.name}}</label>
</span>
<p>Weight: {{weight.name}}</p>
Here is my controller:
$scope.weights = [
{
name: 1,
checked: true
},
{
name: 2,
checked: false
},
{
name: 3,
checked: false
}
];
Here is my Plunker.
How can I get the weight to appear in the paragraph tag?

You should maintain value of radio in one of the ng-model & use $parent. to define it in controller scope rather than in ng-repeat like here
Markup
<body ng-controller="MainCtrl" ng-init="radioValue=1">
<span ng-repeat="weight in weights">
<input type="radio" name="weight" ng-model="$parent.radioValue" ng-value="{{weight.name}}" id="weight{{weight.name}}" ng-checked="weight.checked">
<label for="weight{{weight.name}}">{{weight.name}}</label>
</span>
<p>Weight: {{radioValue}}</p>
</body>
Working Plunkr

The answer lies in understanding how $scope works in angular.
The quick solution is to use $parent.selectedName, where $parent refers to the parent scope. This is because each iteration of ng-repeat creates a scope of itself. (see enter link description here
See this https://jsfiddle.net/pankaj01/Xsk5X/3074/
the JS is
function MyCtrl($scope) {
$scope.weights = [
{
name: 1,
checked: true
},
{
name: 2,
checked: false
},
{
name: 3,
checked: false
}
];
}

Related

Tooltip disappears after disabling and re-enabling BootstrapVue table column

I have a BootstrapVue table which looks like this;
When you hover your mouse on the First Name column, the tooltip Tooltip for First name will appear. The checkboxes at the top will cause the corresponding table columns to appear/disappear.
Here's the description of the bug I encounter.
I uncheck First Name checkbox. Column First Name disappears. Now, I recheck the First Name checkbox. Column First Name reappears again. This is fine. However, the tooltip no longer works when I hover my mouse on the First Name column.
Here's the complete code in a single HTML file.
<link href="https://unpkg.com/bootstrap#4.4.1/dist/css/bootstrap.min.css" rel="stylesheet"/>
<link href="https://unpkg.com/bootstrap-vue#2.2.2/dist/bootstrap-vue.css" rel="stylesheet"/>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.6.10/vue.js"></script>
<script src="https://unpkg.com/bootstrap-vue#2.2.2/dist/bootstrap-vue.min.js"></script>
<div id='app'>
<b-checkbox
:disabled="visibleFields.length == 1 && field.visible"
v-for="field in showFields"
:key="field.key"
v-model="field.visible"
inline
>
{{ field.label }}
</b-checkbox>
<b-table :items="items" :fields="visibleFields" bordered>
</b-table>
<b-tooltip target="HeaderFirst" triggers="hover" container="HeaderFirst">
Tooltip for First name<br>
</b-tooltip>
</div>
<script>
new Vue({
el: '#app',
computed: {
visibleFields() {
return this.fields.filter(field => field.visible)
},
showFields() {
return this.fields.filter(field => field.key.includes('first') || field.key.includes('last'))
}
},
data: dataInit,
})
function dataInit() {
let init_data = {};
init_data.fields = [
{ key: 'id', label: 'ID', visible: true },
{ key: 'first', label: 'First Name', visible: true,
thAttr: {
id: "HeaderFirst"
},
},
{ key: 'last', label: 'Last Name', visible: true },
{ key: 'age', label: 'Age', visible: true },
];
init_data.items = [
{ id: 1, first: 'Mike', last: 'Kristensen', age: 16 },
{ id: 2, first: 'Peter', last: 'Madsen', age: 52 },
{ id: 3, first: 'Mads', last: 'Mikkelsen', age: 76 },
{ id: 4, first: 'Mikkel', last: 'Hansen', age: 34 },
];
return init_data;
}
</script>
I am using vue v2.6, BootstrapVue.
The <b-tooltip>'s target must exist in the DOM upon mounting. It does not dynamically attach a new tooltip to newly created elements in the DOM.
The first run of your code shows a tooltip because <b-table> initially contains the #HeaderFirst element. When you uncheck the First Name box, the existing elements in <b-table> are replaced with new elements via the computed property. The elements removed from the DOM include the one that <b-tooltip> initially attached a tooltip to, and no new tooltip is generated after <b-table> was updated.
Solution
One solution is to render <b-tooltip> only when the target element is visible:
Create a computed prop that determines whether the #HeaderFirst field is visible.
Conditionally render <b-tooltip> based on that computed prop.
new Vue({
computed: { 1️⃣
firstNameHeaderVisible() {
return this.fields.find(field => field.thAttr?.id === 'HeaderFirst')?.visible
}
},
⋮
})
2️⃣
<b-tooltip target="HeaderFirst" v-if="firstNameHeaderVisible">
demo
On disabled elements event hover is not working. You need to wrap element by other e.g. div where you set up tooltip and then it should work well

How can I use multiple b-form-radio-group avoiding visual interference among them?

I'm new using Vue and specifically Bootstrap Vue and I'm trying to build a form with multiple radio groups.
My problem is that when I change the value in one of them the others don't change their values (this was checked with Vue DevTools) but visually it looks like none of the values are selected
I don't know what is wrong with my approach
I post here a simplified version of the code looking for some help, thanks in advance:
<template>
<div>
<b-form-group label="Radio group 1" v-slot="{ ariaDescribedby }">
<b-form-radio-group
id="radio-group-1"
v-model="selected1"
:options="options1"
:aria-describedby="ariaDescribedby"
name="radio-options"
></b-form-radio-group>
</b-form-group>
<b-form-group label="Radio Group 2" v-slot="{ ariaDescribedby }">
<b-form-radio-group
id="radio-group-2"
v-model="selected2"
:options="options2"
:aria-describedby="ariaDescribedby"
name="radio-options"
></b-form-radio-group>
</b-form-group>
</div>
</template>
<script>
export default {
data() {
return {
selected1: 'first',
options1: [
{ text: 'First', value: 'first' },
{ text: 'Second', value: 'second' },
],
selected2: 'one',
options2: [
{ text: 'One', value: 'one' },
{ text: 'Two', value: 'two' },
]
}
}
}
</script>
Since both <b-form-radio-group> elements have the same name, "radio-options", visually they are treated like one group. The different v-model would still function correctly but this isn't what you want visually. Give the second group a different name:
<b-form-radio-group
id="radio-group-2"
v-model="selected2"
:options="options2"
:aria-describedby="ariaDescribedby"
name="radio-options2"
></b-form-radio-group>
Here I changed it to radio-options2.

AngularJS: Hide divs when dropdown is unselected, and output text

I'm still new to AngularJS, and I've tried looking for the solution to my problem but I can't seem to find one that specifically addresses this. Sorry if this has been asked before! And by new, I mean, I'm still pretty clueless on how much of this works.
I have an array of items that I'm displaying with ng-repeat. Each item has a drop down where they can select Yes or No, or leave it unselected. The data is sorted so that anything that's set to Yes or No moves to the top of the list.
I currently also have a checkbox that allows them to Hide an item, which hides it, and moves it to the end of the array, so that it doesn't clutter them up.
I would like to instead have a button that hides all unselected items (a value of neither Yes nor No), instead of making them hide one at a time.
Second: Any item where they've selected Yes should have their names displayed in Field One; Any items where they've selected No should have their names displayed in Field Two.
Here is my code:
var app = angular.module('List', []);
app.controller('MainController', ['$scope', function ($scope) {
$scope.selected = false;
$scope.pList = [
{
id: '1',
title: 'Apples',
checked: false
},
{
id: '2',
title: 'Oranges',
checked: false
},
{
id: '3',
title: 'Bananas',
checked: false
},
{
id: '3',
title: 'Pears',
checked: false
}
];
$scope.pStatus = [
{
stat: 'Unselected',
color: 'black'
},
{
stat: 'Yes',
color: 'green',
},
{
stat: 'No',
color: 'red'
}
];
}]);
<div class="main" ng-controller="MainController">
<div class="container">
<div class="card" ng-repeat="stuff in pList | orderBy: ['checked', 'selectedpStatus', 'id']:false">
<div ng-hide="stuff.checked">
<h2 class="title">{{ stuff.title }}</h2>
<br /><br /><br />
<div class="status" ng-style="{'color':stuff.pStatus.color}">
<select ng-model="stuff.selectedpStatus" ng-options="item.stat for item in pStatus"></select>
</div>
<p class="normal">Hide <label><input type="checkbox" ng-model="stuff.checked" id="{{ stuff.id }}" /></label></p>
</div>
</div>
<br /><br />
<div class="main">
Field One: :{{ stuff.title }}:
<br />
Field Two: :{{ stuff.title }}
</div>
</div>
Thank you for any help!
There are several questions/clarifications I'd typically want to ask, but here's an answer that should guide you further:
Have a property on the scope that stores whether the filter should be applied or not.
You can then filter the array using a filter in the controller, or defined globally. Or, just hide the elements you don't want shown using an ng-if directive on each element.
The logic for showing the title in field 1 vs 2 is simple; the issue is whether you do this for all items, or if you want to somehow select one to show outside of the repeat.
Here's a basic solution though:
<button type="button" ng-click="toggle()">Hide/Show Unselected</button><br>
Hide all: {{ hideAll }}<br />
<div class="card" ng-repeat="stuff in pList | orderBy: ['checked', 'selectedpStatus', 'id']:false"
ng-if="!hideAll || !stuff.selectedpStatus || stuff.selectedpStatus.stat !== 'Unselected'">
<div ng-hide="stuff.checked">
<h2 class="title">{{ stuff.title }}</h2>
<div class="status" ng-style="{'color':stuff.pStatus.color}">
<select ng-model="stuff.selectedpStatus" ng-options="item.stat for item in pStatus"></select>
</div>
stuff.selectedpStatus: {{ stuff.selectedpStatus }}<br>
Field One: {{ stuff.selectedpStatus && stuff.selectedpStatus.stat === 'Yes' ? stuff.title : '' }}<br />
Field Two: {{ stuff.selectedpStatus && stuff.selectedpStatus.stat === 'No' ? stuff.title : '' }}<br />
</div>
</div>
and
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope) {
$scope.selected = false;
$scope.hideAll = false;
$scope.pList = [{
id: '1',
title: 'Apples',
checked: false
}, {
id: '2',
title: 'Oranges',
checked: false
}, {
id: '3',
title: 'Bananas',
checked: false
}, {
id: '3',
title: 'Pears',
checked: false
}];
$scope.pStatus = [{
stat: 'Unselected',
color: 'black'
}, {
stat: 'Yes',
color: 'green',
}, {
stat: 'No',
color: 'red'
}];
$scope.toggle = function() {
$scope.hideAll = !$scope.hideAll;
}
});
In a plunkr: https://plnkr.co/edit/PBr753nznrMwsgAIsTwE?p=preview

EmberJS - Checkboxes and Getting Values in Controller

Below is a simple example how I intend to use check boxes. What I have is an array of terms with id and name field and each post can be assigned to a single or multiple terms/categories.
var config = {};
config.terms = [
{id: 1, termName: 'Red'},
{id: 2, termName: 'Green'},
{id: 3, termName: 'Blue'}
];
Problem
With EmberJS handlebar expression I am showing those checkboxes but I am confused what to use as form element variable name field doesn't seem to defined in the controller. The checked field works as controller property but when I add termName as checked all of the checkboxes are checked by default and label after checking changes after clicking checkboxes.
What I need to get on the controller is the term names that are selected
Below is the example code. You can also find it on JsFiddle. Check uncheck the red/green/blue checkboxes to see the problem. Also have a look in console.
HTML
<div id="main"></div>
<script type="text/x-handlebars" data-template-name="index">
{{#each term in terms}}
{{input type="checkbox" name=term.name}} {{term.name}}
{{/each}}
<button {{action "submit"}}>Submit</button>
</script>
JS
var config = {};
config.terms = [
{id: 1, name: 'Red'},
{id: 2, name: 'Green'},
{id: 3, name: 'Blue'}
];
App = Ember.Application.create({
rootElement: '#main'
});
App.IndexRoute = Ember.Route.extend({
setupController: function(controller){
controller.set('terms', config.terms);
}
});
App.IndexController = Ember.Controller.extend({
actions: {
submit: function(){
console.log(this.Red);
console.log(this.Blue);
console.log(this.Green);
}
}
});
In you jsfiddle example you'r binding the name to the checked value of the checkbox. I think that's not what you want to do.
The checked value should be bound to a boolean value.
So,
1st approach: either add a property to your term object (selected: false)
config.terms = [
{id: 1, name: 'Red', selected: false },
{id: 2, name: 'Green', selected: false },
{id: 3, name: 'Blue', selected: false }
];
(as Ember objects:)
config.terms = [
Em.Object.create({id: 1, name: 'Red', selected: false }),
Em.Object.create({id: 2, name: 'Green', selected: false }),
Em.Object.create({id: 3, name: 'Blue', selected: false })
];
and then bind the property in your template this way:
{{input type="checkbox" checked=term.selected}}
2nd approach: bind it to controller properties:
// inside your controller:
redSelected: false,
greenSelected: false,
blueSelected: false,
{{input type="checkbox" checked=controlller.redSelected}}

Radio button ng-model to true/false (checked/unchecked)

I'm trying to bind a radio button to true when the radio button is selected and to false when the radio button is not selected. I must be missing something really obvious because I haven't been able to do it yet.
I have a simple collection, eg:
$scope.collection = [
{ id: 1, selected: true},
{ id: 2, selected: false},
{ id: 3, selected: false}];
And I wish to bind the "selected" property to whether the radio button is checked or not. Sounds simple enough but ng-model binds to undefined. ng-checked almost works, it displays the correct result but never actually updates the value...
Plunkr with the problem
You can bind the radio buttons to the right object fields in from the controller $scope:
angular.module('ExampleApp', [])
.controller('ExampleCtrl', ['$scope', function ($scope) {
$scope.radioContent = [
{txt: 'One', checked: false},
{txt: 'Two', checked: false}
];
$scope.$watch('radioContent', function (now, then) {
console.debug('Something changed', now);
}, true);
}]);
And the HTML:
<div ng-app="ExampleApp" ng-controller="ExampleCtrl">
<div ng-repeat="radio in radioContent">
<input type="radio" ng-model="radio.checked">{{radio.txt}}
</div>
</div>
Here's a working Fiddle
Seems like ng-bind and ng-selected don't work that well with radio buttons, but if you change the radio buttons to be checkboxes, the code works as expected.
And using #Ashesh's answer, the radio.checked property of a button still becomes undefined after messing with the radio button once.
Working plunkr
<!DOCTYPE html>
<html>
<head>
<script data-require="angular.js#*"
data-semver="1.3.0-beta.5"
src="https://code.angularjs.org/1.3.0-beta.5/angular.js"></script>
<script>
angular.module("sampleapp", [])
.controller('samplecontroller', function($scope,$rootScope) {
$scope.collection = [
{ id: 1, selected: true},
{ id: 2, selected: false},
{ id: 3, selected: false}];
});
</script>
</head>
<body ng-app="sampleapp" ng-controller="samplecontroller">
<div class="radio" ng-repeat="element in collection">
<span ng-bind="element.id"></span>
<span ng-bind="element.selected"></span>
<input type="checkbox" name="whatever" ng-model="element.selected">
</div>
</body>
</html>
However, if you change the selected property into true or false and NOT "true" or "false", it works.

Categories

Resources