Using AngularJS to show divs based on select value - javascript

I'm trying to use an HTML select element's value to show or hide certain div tags with AngularJS. Here is my code:
<body ng-app="kiosk" id="ng-app" >
<div class="page" ng-controller="kiosk-controller" ng-cloak="true">
<section class="signin">
<div class="intro">
<h1 id="service-desk-name">{{servicedeskname}}</h1><br></br>
<h4 id="welcome">{{welcome}}</h4>
</div>
<hr></hr>
<form id="form" name="form">
<div>
<label>Do you have an ID?</label><br></br>
<select type="select"
ng-model="user.affiliated"
ng-required="true"
ng-options="opt as opt.name for opt in affiliate.affiliateOptions">
<option value="">--Select an answer--</option>
</select>
</div>
<div ng-switch="user.affiliated">
<div ng-switch-when="Yes">
<!--><-->
</div>
<div ng-switch-when="No">
<!--><-->
</div>
</div>
And here is the Javascript snippet:
var kiosk = angular.module('kiosk',[]);
kiosk.controller('kiosk-controller', ['$scope', function($scope, $user) {
$scope.servicedeskname = 'Service Desk';
$scope.welcome = 'Please sign in and a consultant will be with you shortly.';
$scope.affiliate = {affiliateOptions:[]};
$scope.affiliate.affiliateOptions = [
{ name: 'Yes' },
{ name: 'No' }
];
/*other stuff*/
};
I can't figure out the proper way to reference the select options in the HTML tags using ng directives. Unless it's not super clear, I want to be able to show one div if the select value is "Yes", and show another if the select value is "No".

I think the switch statement you use need small modification
<div ng-switch on="user.affiliated">
<div ng-switch-when="Yes">
<!--><-->
</div>
<div ng-switch-when="No">
<!--><-->
</div>
</div>
check this ng-switch documentation for more help

I believe you're looking for ng-show and ng-hide.
<div ng-show="user.affiliated === 'Yes'"></div>
<div ng-show="user.affiliated === 'No'"></div>
And try changing this line to this:
ng-options="opt.name as opt.name for opt in affiliate.affiliateOptions">

You forgot the name property in the switch statement.
- <div ng-switch="user.affiliated">
+ <div ng-switch="user.affiliated.name">
As can be viewed in jsfiddle

you just have a little mistake. you must have user.affiliated.name instead of user.affiliated
like this
<div ng-switch="user.affiliated.name">
<div ng-switch-when="Yes">
yes
</div>
<div ng-switch-when="No">
no
</div>
</div>

Related

Display a form with multiple ng-repeat after all content has been loaded

I have a form with multiple ng-repeat block and other blocks without ng-repeat. How do I wait until the all content has been loaded before rendering the form
As an example
<form name="forms.confirmForm" ng-submit="submitForm()">
<div>
<div ng-repeat="phone in candidate.phones" style="position:relative">
-- write out some value
</div>
<div class="small-12">
<label>first name
</label>
<input name="firstName" type="text" />
<div ng-repeat="phone in candidate.email" style="position:relative">
-- write out some value
</div>
</div>
<div class="apply-bar">
<button class="button button-apply" type="submit">
apply
</button>
</div>
</form>
** The information comes from a model and it is loaded once . The ng-repeat is just taking parts of the model and iterating
use ng-if to check whether array items have been loaded.
<form name="forms.confirmForm" ng-submit="submitForm()"
ng-if="candidate.phones.length > 0 && candidate.email.length > 0">
There are two ways you can handle this.
You initialise your model (candiate) with an empty array of phones/email. In which case you don't need to do anything in the template as the ng-repeat will apply 0 times. Resulting in nothing being rendered.
You use ng-if to prevent rendering when you don't have your model(candidate) and/or ng-if to prevent your ng-repeat trying to render when your model doesn't have phone/emails.
Try this based on the second option;
<form name="forms.confirmForm" ng-submit="submitForm()">
<div ng-if="candidate"> <!--Prevent rendering if there is no candiate model-->
<div
ng-if="candidate.phones" <!--Prevent rendering if canidate doesn't have phones param-->
ng-repeat="phone in candidate.phones"
style="position:relative"
>
-- write out some value
</div>
<div class="small-12">
<label>first name
</label>
<input name="firstName" type="text"/>
<div
ng-if="candidate.email"
ng-repeat="phone in candidate.email"
style="position:relative"
>
-- write out some value
</div>
</div>
<div class="apply-bar">
<button class="button button-apply" type="submit">
apply
</button>
</div>
</div>
</form>
You can use ng-if in your div :
<div ng-if="candidate.phones">
<div ng-repeat="phone in candidate.phones" style="position:relative">
-- write out some value
</div>`

how to use ng-show to display specific divs inside an ng-repeat?

I have an ng-repeat div to dynamically display a set of div tags based on a dynamic list of items, that each have a unique Id , a type and a "title" value which are both strings and I have a click function assigned to each of them. When I want to click on one of these divs , I want to display an separate div associated to that clicked div and I want to do that using an ng-show which at the moment has a condition where the id of this item/div should be equal/equivalent to a
scope variable I've defined in a controller associated with the html for this new div to be displayed.
The problem I'm getting is that every one of these separate divs is showing and assuming that all the ng-shows are true which shouldn't be the case and I'm not sure why this is happening as all the id's for the items are unique. I've printed out to the console and can't see anything wrong with the assigning of the variable but not sure if I've missed something with regards to the ng-show condition.
Here is what I have so far in html with 2 div examples (don't worry about replicating all the styling, i just want to figure out what is going on with the html/angular stuff):
<div class="col-md-12 col-sm-12 col-xs-12 " ng-repeat="item in items track by item.id" ng-click="onClick(item.id)">
//first type div that is clickable
<div class="row">
<div>
<header class="text">
<h1 data-ng-if="item.title" ng-bind-html="item.title"></h1>
</header>
</div>
</div>
//div to be displayed after associated first div type is clicked
<div class=" col-sm-11 row" ng-show="displayMessage===item.id" >
<header class="col-sm-12 text">
<h1 data-ng-if="item.title" ng-bind-html="item.title"></h1>
</header>
<p class="col-sm-12" > text about {{item.id]} </p>
</div>
//2nd type of div
<div class="row" style=" background: linear-gradient(135deg, #156570, #1e9d8b);">
<h1 data-ng-if="item.title" ng-bind-html="item.title"></h1>
<i class="ms-icon ms-icon-heart-rate"></i>
<div class="clearfix"></div>
</div>
//div to be displayed after associated second div is clicked
<div class="col-md-11 col-sm-11 col-xs-11" ng-show="displayMessage===item.id">
<div style="background: linear-gradient(135deg, #156570, #1e9d8b);"></div>
<h1 class="col-sm-12 col-xs-12" data-ng-if="item.title" ng-bind-html="item.title" style="color:#000"></h1>
<p class="col-sm-12 col-xs-12 "> text associated with {{item.id}}
</p>
</div>
</div>
And here is the simple click function I have . $scope.displayMessage is defined earlier on during the controller setup where its set to an empty string:
$scope.onClick = function (itemId) {
$scope.displayMessage = itemId;
}
Let me know if I need to add more code.
It could be done in a simpler way without adding property to the items varible you have in scope.
Let the Controller be
app.controller('MainCtrl', function($scope) {
$scope.div_=[];
$scope.items = [
{
id: 1,
title: "first item"
},
{
id: 2,
title: "second item",
},
{
id: 3,
title: "third item",
}
];
$scope.onClick=function(index,row){
$scope.div_[index+'_'+row]=true;
}
});
HTML will be like
<body ng-controller="MainCtrl">
<div ng-repeat="item in items">
<div style="color:red" ng-click="onClick($index,0)">DIV {{$index}}.0---click to show DIV {{$index}}.0_CHILD</div>
<div style="color:blue" ng-show="div_[$index+'_0']">DIV {{$index}}.0_CLILD</div>
<br>
<div style="color:red" ng-click="onClick($index,1)">DIV {{$index}}.1---click to show DIV {{$index}}.1_CHILD</div>
<div style="color:blue" ng-show="div_[$index+'_1']">DIV {{$index}}.1_CLILD</div>
<hr>
</div>
</body>
Here an array named 'div_' is maintained to trace all ng-show value of all div.
Working plunker https://plnkr.co/edit/uhFdCXkmS4gB95c9bjTR?p=preview
This will be easier for you to accomplish if you had properties on each item to key off of.
For example,
$scope.items = [
{
id: 1,
title: "first item",
isFirstDivSelected: false,
isSecondDivSelected: false
},
{
id: 2,
title: "second item",
isFirstDivSelected: false,
isSecondDivSelected: false
}
{
id: 3,
title: "third item",
isFirstDivSelected: false,
isSecondDivSelected: false
}
];
This will allow you to add an ng-click to your children items.
<div class="col-md-12 col-sm-12 col-xs-12 " ng-repeat="item in items track by item.id" ng-click="onClick(item.id)">
//first type div that is clickable
<div class="row" ng-click="item.isFirstDivSelected = true;">
<div>
<header class="text">
<h1 data-ng-if="item.title" ng-bind-html="item.title"></h1>
</header>
</div>
</div>
//div to be displayed after associated first div is clicked
<div class=" col-sm-11 row" ng-show="item.isFirstDivSelected" >
<header class="col-sm-12 text">
<h1 data-ng-if="item.title" ng-bind-html="item.title"></h1>
</header>
<p class="col-sm-12" > text about {{item.id]} </p>
</div>
//more divs.........
Right now, there is no good way to for your application to know that any of your children divs have been clicked. There are other ways you can do this, but in my opinion, adding properties that are well defined and straightforward is the best way.
if you want to show hide rows under loop
<div *ngFor="let client_obj of dashboard_data.data.items ;let i = index" >
<input type="checkbox" [(ngModel)]="div_['level_1_'+i]">
<div [class.hide]="div_['level_1_'+i]" >
{{client_obj.value}}
</div>
</div>

Only show parent if child contains certain string

I have a group of divs that appear on multiple pages, that have this pattern:
<div class=“entry”>
<div id=“post”>
<div class=“text”>
<div class=“service”></div>
<div class=“timeline”>
<div class=“entry-title”>
#hashtagOne
</div>
</div>
</div>
</div>
</div>
<div class=“entry”>
<div id=“post”>
<div class=“text”>
<div class=“service”></div>
<div class=“timeline”>
<div class=“entry-title”>
#hashtagTwo
</div>
</div>
</div>
</div>
</div>
<div class=“entry”>
<div id=“post”>
<div class=“text”>
<div class=“service”></div>
<div class=“timeline”>
<div class=“entry-title”>
#hashtagThree
</div>
</div>
</div>
</div>
</div>
This group appears on multiple pages.
My ideal javascript/jquery solution is something like this:
display:none on all div class="entry"
if child div class="entry-title" contains #something, change parent div class="entry" to display:block
so that on Page One I can insert this code to only show #hashtagOne, on Page Two only #hashtagTwo, etc. etc.
Try something like this:
$('.entry-title').each(function(i,v){
if ($(this).text().trim().charAt(0) =="#") {
$(this).closest('.entry').show();
}
});
https://jsfiddle.net/0ybstx9o/
This simply works fine :
$(document).ready(function(){
$(".entry").each(function(){
if($(this).find(".entry-title:contains('#something')").length > 0){
$(this).css("display","block");
}
});
});
Its pretty simple, just use :contains() and .closest() together either on page load or whatever event you want this display:block behavior to run.
As you want to show based on differnt pages, I suggest to use page title and set it to title="Page One" and title="Page Two" etc and then compare it in document ready state and show accordingly the desired div
jQuery(document).ready(function(){
jQuery('div.entry').hide();
if(jQuery(document).find("title").text() == 'Page One')
{
jQuery( "div.entry-title:contains('#something')" ).closest('.entry').show();
}
else if(jQuery(document).find("title").text() == 'Page Two')
{
jQuery( "div.entry-title:contains('#something Else')" ).closest('.entry').show();
}
});
$(".entry").find(".entry-title").text(function(key, text) {
if (text.indexOf("#")>=0) {
$(this).parents(".entry").hide()
}
})
Here is the working Plunker

Tag input not showing up

Why isn't the tag input showing up?
<div ng-controller="DrawingsController">
<tags-input ng-model="tags"></tags-input>
<div class="controls">
<label>Filter:</label>
<button class="filter" data-filter="all">All</button>
<button class="filter" data-filter=".name-{{name}}" ng-repeat="name in names">{{name}}</button>
</div>
<div class="test">
<div id="MixItUpContainer1" class="container">
<div class="mix name-{{drawing.name}}" data-myorder="{{drawing.value}}" ng-repeat="drawing in drawings">Value : {{drawing.name}}</div>
</div>
</div>
The tag input works on other pages but it's not showing up on this one.
JS Fiddle:
http://jsfiddle.net/ce1qzjv1/
Update:
This is my updated fiddle: jsfiddle.net/og19nL11/1
I want them to show up in their own value box like the others but it's not working
In the fiddle you posted, ngTagsInput is not referenced. You should add it as a dependency of your application.
var app = angular.module('app', ['ngTagsInput']);

Inner ng-repeat is skipping the first item of my array, and putting them into the last html element

I have a JSON array that I'm trying to convert and display as HTML using angular's ng-repeat.
My JSON is of the form:
data:{
thing_one:[{
id:1,
fields:[{ .... }]
},
{
id:2,
fields:[{ .... }]
}],
separate_thing:[{
id:1,
fields:[{ .... }]
},
{
id:2,
fields:[{ .... }]
}]
}
And in my controller for that page:
I have:
MockFields.get(function(data){
$scope.thing_one = data.thing_one;
$scope.separate_thing = data.separate_thing;
}
And a stripped down version of my html is:
<div class="details">
<div class="my_header">
<h2>Thing 1</h2>
</div>
<div class="thing_one">
<dynamic-form fields="thing_1[0].fields"><dynamic-form>
</div>
</div>
<div class="details">
<div class="my_header">
<h2>Separate Thing</h2>
</div>
<div class="separate_thing" ng-repeat="thing in separate_thing>
<dynamic-form fields="thing.fields"><dynamic-form>
</div>
</div>
Where <dynamic-form> is a custom directive, where I repeat over my fields, and use an ng-switch on=... to pick a field type. It looks a little something like this (again cut down)
<div ng-repeat='field in fields track by field.order'>
<label>{{field.display}}</label>
<span ng-switch on='field.fieldtype'>
<span ng-switch-when="text">
<input type="text"/>
</span>
<span ng-switch-when="....">
<input type="...."/>
</span>
.
.
.
.
</span>
</div>
What I'm seeing however is that all of my fields from both things in separate_thing are in the last <dynamic-form> and the first one is empty.
This is what I see when I inspect that element/section of the DOM:
<div class="details">
<div class="my_header">
<h2>Separate Thing</h2>
</div>
<div class="separate_thing" ng-repeat="thing in separate_thing></div>
<div class="separate_thing" ng-repeat="thing in separate_thing>
<div>
<label>Foo from separate thing 1</label>
<input type="text">
.....
</div>
<div>
<label>Foo from separate thing 2</label>
<input type="text">
.....
</div>
</div>
</div>
Is this an optimization from angular? Or have I done something wrong? I'm a little lost as I've not seen any errors from my code.
Why is it pushing all my sub-objects (fields) to the last element?
This might have been a bug.
Angular directives fail to compile when they have multiple elements without a containing element, which my previous set up had (via ng-repeat)
Instead inside my directive, I've now wrapped the div with ng-repeat inside an out div.
So I now have:
<div>
<div ng-repeat='field in fields track by field.order'>
<label>{{field.display}}</label>
<span ng-switch on='field.fieldtype'>
<span ng-switch-when="text">
<input type="text"/>
</span>
<span ng-switch-when="....">
<input type="...."/>
</span>
.
.
.
.
</span>
</div>
</div>
And it all seems happy.

Categories

Resources