AngularJS and Angular-UI Bootstrap tabs scope - angularjs

I am using AngularJS and Angular-UI Bootstrap tabs. This is my controller:
app.controller("SettingsCtrl", ['$scope','SettingsFactory','$stateParams', function($scope,SettingsFactory,$stateParams){
$scope.navType = 'pills';
$scope.saveLanguage = function()
{
console.log($scope.test.vari); // loged undefined
}
}]);
My view
<div class="row clearfix">
<tabset>
<tab heading="Jezik">
<form role="form" name="test">
<div class="form-group">
<label for="lang">Izaberite jezik</label>
<select class="form-control" ng-model="vari">
<option>Hrvatski</option>
<option>Srpski</option>
<option>Bosanski</option>
<option>Engleski jezik</option>
<option>Njemački jezik</option>
</select>
</div>
<button type="submit" class="btn btn-default" ng-click="saveLanguage()">Save</button>
</form>
</tab>
</div>
Can someone help me to see why is loging undefined when I am using Angular-UI Bootstrap Tabs. Is it creating own scope. How tu access model value ?

This code solved my problem (removed name atribute from form, added ng-model="test.vari", and added $scope.test= {} in my controller) :
<tabset>
<tab heading="Jezik">
<form role="form">
<div class="form-group">
<label for="lang">Izaberite jezik</label>
<select class="form-control" ng-model="test.vari">
<option>Hrvatski</option>
<option>Srpski</option>
<option>Bosanski</option>
<option>Engleski jezik</option>
<option>Njemački jezik</option>
</select>
</div>
<button type="submit" class="btn btn-default" ng-click="saveLanguage()">Spremi Jezik</button>
</form>
</tab>
</div>
app.controller("SettingsCtrl", ['$scope','SettingsFactory','$stateParams', function($scope,SettingsFactory,$stateParams){
$scope.navType = 'pills';
$scope.test= {};
$scope.saveLanguage = function()
{
console.log($scope.test.vari);
// SettingsFactory.update({ id:$stateParams.user_id }, $scope.language);
}
}]);

The tab creates child scopes so we need to bind it to an expression that evaluates to a model in the parent scope.
For this, the model must use a . like this:
ng-model='object.variable'
And we must declare the object in controller's top:
$scope.object = {};
Example:
angular.module('test', ['ui.bootstrap']);
var DemoCtrl = function ($scope) {
$scope.obj = {text: ''};
$scope.show = function() {
alert('You typed: ' + $scope.obj.text)
}
};
<!doctype html>
<html ng-app="test">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="http://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.14.0.js"></script>
<link href="//netdna.bootstrapcdn.com/bootstrap/3.0.3/css/bootstrap.min.css" rel="stylesheet">
</head>
<body>
<div ng-controller="DemoCtrl">
Value outside the tabs: {{obj.text}}
<uib-tabset>
<uib-tab heading="Tab 1">
<input ng-model="obj.text">
<button ng-click="show()">Show</button>
</tab>
</tabset>
</div>
</body>
</html>

Related

How to get selected option in be selected in a dropdown after opening a modal in AngularJS?

I have a select tag like this:
<select... ng-model="someProperty" ng-change="openSomeDialog()">
<option value=""></option>
<option value="Test1">Test1</option>
<option value="Test2">Test2</option>
</select>
The openSomeDialog() function opens a ui.bootstrap.modal directive modal. When the user closes the modal, the dropdown reverts to the initial option which is the empty one (first option) instead of what the user has selected. I also tried to use a watch on the select's ngModel and I get the same issue.
If I put some non modal related logic in the function instead of opening a modal, the selection works fine so it seems the process of opening the modal changes the events workflow or something.
How do I get the dropdown to select what the user has selected before the modal opened, after the modal closes?
I think this might be useful-> https://stackoverflow.com/a/1033982/7192927
Try binding the "selected" attribute to an object/variable as required to your case.
If you are using AngularJS, Instead of using select, you can use md-select of angular material, where u have the trackby attribute to make the option appear
as selected.--> https://material.angularjs.org/latest/api/directive/mdSelect
Ng-Options
Try using ng-options:
// Script
$scope.datarray = ["test1, "test2"];
<!-- HTML -->
<select class="form-control" ng-options="test in dataArray" ng-model="someProperty" ng-change="openSomeDialog()">
<option value=""></option>
</select>
https://embed.plnkr.co/wF3gc5/
EDIT: Updated my answer to better align with your requirements / comment.
Reference
https://docs.angularjs.org/api/ng/directive/select
Snippet
(function() {
"use strict";
var app = angular.module('plunker', ['ui.bootstrap']);
app
.controller("MainCtrl", MainCtrl)
.controller("ModalController", ModalController);
MainCtrl.$inject = ["$scope", "$log", "$uibModal"];
function MainCtrl($scope, $log, $uibModal) {
// Sample Data
$scope.cats = [{
id: 0,
name: "mister whiskers"
}, {
id: 1,
name: "fluffers"
}, {
id: 2,
name: "captain longtail"
}];
$scope.openModal = function() {
// Open the modal with configurations
var modalInstance = $uibModal.open({
templateUrl: 'myModalContent.html', // Points to my script template
controller: 'ModalController', // Points to my controller
controllerAs: 'mc',
windowClass: 'app-modal-window',
resolve: {
cats: function() {
// Pass the Cats array to the Modal
return $scope.cats;
},
selectedCat: function() {
// Pass the selected cat to the Modal
return $scope.selectedCat;
}
}
});
// Handle the value passed back from the Modal
modalInstance.result.then(function(returnedCat) {
if (returnedCat === null || returnedCat === undefined) {
// Do Nothing
return;
}
// We can now update our main model with the modal's output
$scope.selectedCat = returnedCat;
});
}
}
ModalController.$inject = ['$scope', '$timeout', '$uibModalInstance', 'cats', 'selectedCat'];
function ModalController($scope, $timeout, $uibModalInstance, cats, selectedCat) {
// Assign Cats to a Modal Controller variable
console.log("cats: ", cats)
$scope.modalCats = cats;
if (selectedCat !== null || selectedCat !== undefined) {
$scope.selectedModalCat = selectedCat;
}
$scope.submit = function() {
// Pass back modified resort if edit update successful
$uibModalInstance.close($scope.selectedModalCat);
}
$scope.close = function() {
// Pass back modified resort if edit update successful
$uibModalInstance.close(null);
}
}
})();
<!DOCTYPE html>
<html ng-app="plunker">
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<link rel="stylesheet" href="style.css" />
<link data-require="bootstrap-css#3.*" data-semver="3.3.7" rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.css" />
<!-- JQuery and Bootstrap -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
<!-- Angular Stuff -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.9/angular.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.9/angular-touch.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.9/angular-animate.js"></script>
<!-- UI Bootstrap Stuff -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-bootstrap/2.5.0/ui-bootstrap-tpls.min.js"></script>
<!-- OUR Stuff -->
<script src="app.js"></script>
<script src="modalController.js"></script>
</head>
<body ng-controller="MainCtrl">
<!-- ==== MAIN APP HTML ==== -->
<div class="container">
<div class="row">
<div class="col-xs-12">
<div class="jumbotron text-center">
<h3>AngularJS - ngOptions and UI Bootstrap Modal</h3>
</div>
</div>
<div class="col-xs-12">
<form class="form">
<div class="form-group">
<label class="form-label">Select Profile:</label>
<select class="form-control" ng-options="cat.name for cat in cats track by cat.id" ng-model="selectedCat" ng-change="openModal()">
<option value="">-- Cat Selection --</option>
</select>
</div>
<div class="well form-group" ng-show="selectedCat !== undefined && selectedCat !== null">
<label>Selected: </label>
<pre>{{ selectedCat }}</pre>
</div>
</form>
</div>
</div>
</div>
<script type="text/ng-template" id="myModalContent.html">
<div class="modal-header">
<h3 class="modal-title" id="modal-title">I'm a modal!</h3>
</div>
<div class="modal-body" id="modal-body">
<select class="form-control" ng-options="modalCat.name for modalCat in modalCats track by modalCat.id" ng-model="selectedModalCat">
<option value="">-- Cat Selection --</option>
</select>
</div>
<div class="modal-footer">
<button class="btn btn-primary" type="button" ng-click="submit()">OK</button>
<button class="btn btn-warning" type="button" ng-click="close()">Cancel</button>
</div>
</script>
</body>
</html>
Actually I have found the issue in 'my' code. After closing the modal, it was retrieving data that caused the property bound to the select to refresh as well.
Angular Bootstrap modal Doesn't save the state when the it's closed. You must perform some alternative code to save the user state when they closed the browser or store it in cookie. After that when the user open again the modal you must fetch it and display it in your
<select....... ng-change="openSomeDialog()">...</select>

Angular Wiring up two controllers from Model to auto fill form

I've got an angular app I'm working on where I'm trying to auto fill a pop up modal based on a user's selection.
I thought I could use my model service to keep track of what the user selected and 'wire' the controller for the <select> list and it's edit button to the model but that doesn't seem to work.
Adding to the complexity I'm using angular-route and my <select> list is buried in a view. I was trying to keep my pop up modals in a separate controller outside the view because they've got their own templates and I had problems when I nested them into the view...
I've seen a few examples of wiring up angular apps and thought I understood them but I can't figure out what I'm doing wrong.
EDIT (thanks Pankaj Parkar for pointed out my mistakes in the plunker):
I have a plunker here:
https://plnkr.co/edit/6f9FZmV8Ul6LZDm9rcg9?p=preview
Below is the snipped in a single HTML page with CDN links :).
Am I just completely misunderstanding how angularjs is suppose to work?
<html ng-app="myApp">
<head>
<title>Bootstrap 3</title>
</head>
<meta name="viewport" content="width=device-width, initial-scale=1.0"/>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<body>
<div ng-view></div>
<script id="editables.html" type="text/ng-template">
<div class="container">
<div class="jumbotron">
<form>
<div class="form-group">
<select class="form-control" id="mapsSelect" size="10" multiple ng-model="model.selected">
<option ng-repeat="n in editables">{{n}}</option>
<select>
</div>
<a href="#editModal" class = "btn btn-info" data-toggle="modal" ng-click="edit()" >Edit</a>
</form>
</div>
</div><!--end container div-->
</script>
<div ng-controller="modalsController">
<div id="editModal" class="modal fade" role="dialog">
<div class="modal-dialog">
<div class="modal-content">
<form class="form-horizontal">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
<h4>New Map</h4>
</div>
<div class="modal-body">
<div class="form-group">
<label for="name" class="col-lg-3 control-label">Name</label>
<div class="col-lg-9">
<input type="text" class="form-control" id="name" ng-model="formModel.name"></input>
</div>
</div>
<div class="form-group">
<label for="desc" class="col-lg-3 control-label">Description</label>
<div class="col-lg-9">
<input type="text" class="form-control" id="desc" ng-model="formModel.desc"></input>
</div>
</div>
<div class="modal-footer">
<pre> {{ formModel | json }}<br><br>Working: {{ workingMap }}</pre>
Cancel
Continue
</div>
</form>
</div>
</div>
</div><!-- end modal -->
</div>
</body>
<script src = "https://ajax.googleapis.com/ajax/libs/jquery/3.1.0/jquery.min.js"></script>
<script src = "https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script>
<script src = "https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular-route.min.js"></script>
<script src = "https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<!-- <script src = "js/script.js"></script> -->
<script>
var app = angular.module('myApp', ['ngRoute']);
var modelService = function ($log){
var moduleHello = function(myMessage){
console.log("Module hellow from myService " + myMessage);
}
var moduleNames = {
"First" : {desc: "First's Description"},
"Second" : {desc: "Second's Description"},
"Third" : {desc: "Third's Description"}
};
var moduleWorkingName = {};
return {
hello: moduleHello,
editables: moduleNames,
workingName: moduleWorkingName
}
}//end modelService
app.factory("modelService", ["$log", modelService]);
app.config(['$routeProvider', function($routeProvider) {
$routeProvider.
when('/editables', {
controller: "editablesController",
templateUrl: "editables.html"
}).
otherwise({
redirectTo: "/editables"
});
}]);
app.controller('editablesController', ['$scope', '$log','modelService', function($scope,$log, $modelService) {
$scope.model = {};
//console.log( JSON.stringify( $modelService.editables ) );
$scope.editables = [];
for ( name in $modelService.editables){
$scope.editables.push( name );
}
$scope.edit = function(){
if ( typeof $modelService.editables [$scope.model.selected] != 'undefined'){
$modelService.workingName = $modelService.editables [$scope.model.selected];
console.log ("Setting my working name to " + JSON.stringify( $modelService.workingName ) );
}else{
console.log ("Nothing Selected");
}
}
}]);
app.controller('modalsController', ['$scope','modelService', function($scope,$modelService) {
$scope.formModel = {};
$scope.formModel.name = "Hard coding works of course";
$scope.formModel.desc = $modelService.workingName.desc; //But I can't seem to get this to update. I thought pointing it at an object in the Model would be enough.
console.log("Firing up modalsController");
}]);
</script>
</html>
I spent the last two days mulling over this in my head and I think I figured it out. For starters, here's the (working) plunker:
https://plnkr.co/edit/Kt3rebPtvGTt0WMXkQW4?p=preview
Now, the explanation. I was trying to keep a separate 'formModel' object that kept track of the controller's state. But that's both silly and pointless.
Instead what you're supposed to do is:
a. Create an object in your service to hold all your data (I just called this 'model')
b. For each controller that needs to share data create a variable on the $scope of the controller and point it to your 'model' variable from your service.
c. after that use the variables from your model in your html.
So in both my controllers you'll find this line:
$scope.model = $modelService.model;
and in my HTML you'll find stuff like this:
<input type="text" class="form-control" id="name" ng-model="model.workingName.name"></input>
notice how I'm using "model.workingName.name"? This references $scope.model.workingName.name, which thanks to the line $scope.model = $modelService.model from my JavaScript now points directly to my model.
And that is how you "wire up" Angular.
By the way, experienced Angular folks have probably noticed that this part:
$scope.editables = [];
for ( name in $modelService.model.names){
$scope.editables.push( name );
}
probably belongs in a directive instead of a controller because I'm editing the DOM.
Stuff like that's what makes it so hard to learn AngularJS. There's so many concepts to get the hang of.

while creating radio buttons using ng-repeat & ng-view model value is not getting reflected in controller

I am trying to render a page using ng-view in that I am using ng-repeat to render my radio buttons and the ng-model which is there not updating my value in controller..
MY HTML
<div ng-repeat="role in Roles">
<input type="radio" ng-model="Role"
value="role" ng-value="role"
name="Roles"
id={{role}}>
<span>{{role}}</span>
</div>
MY CONTROLLER
console.log("Moving Forward--"+$scope.Role);
on console printing undefined..
Your code works fine for me, however you can set an object on the $scope to set your properties which you get when the user interacts as a single data source which will be same when updated from different controllers/sources.
Works fine like the way you do check below example
angular
.module('demo', [])
.controller('DefaultController', DefaultController);
DefaultController.$inject = ['$scope'];
function DefaultController($scope) {
$scope.availableRoles = ['Admin', 'Manager', 'User'];
$scope.logSelectedRole = logSelectedRole;
function logSelectedRole() {
console.clear();
console.log("Moving Forward -- " + $scope.selectedRole);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="demo">
<div ng-controller="DefaultController">
<div ng-repeat="role in availableRoles">
<input type="radio" ng-model="$parent.selectedRole" value="role" ng-value="role" name="Roles" id="{{role}}"/> <span style="display: inline-block; line-height: 28px;">{{role}}</span>
</div>
<button ng-click="logSelectedRole()">Log to console</button>
</div>
</div>
Same example using controller aliasing
angular
.module('demo', [])
.controller('DefaultController', DefaultController);
function DefaultController() {
var vm = this;
vm.availableRoles = ['Admin', 'Manager', 'User'];
vm.logSelectedRole = logSelectedRole;
function logSelectedRole() {
console.clear();
console.log("Moving Forward -- " + vm.selectedRole);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="demo">
<div ng-controller="DefaultController as ctrl">
<div ng-repeat="role in ctrl.availableRoles">
<input type="radio" ng-model="ctrl.selectedRole" value="role" ng-value="role" name="Roles" id="{{role}}"/> <span style="display: inline-block; line-height: 28px;">{{role}}</span>
</div>
<button ng-click="ctrl.logSelectedRole()">Log to console</button>
</div>
</div>
Check this video and the below example about the difference when you create an object on the $scope and assign your properties on them instead of assigning directly. I recommend you to use the below approach instead of using $parent.something or use controller aliasing syntax.
angular
.module('demo', [])
.controller('DefaultController', DefaultController);
DefaultController.$inject = ['$scope'];
function DefaultController($scope) {
$scope.data = {
selectedRole: undefined
};
$scope.availableRoles = ['Admin', 'Manager', 'User'];
$scope.logSelectedRole = logSelectedRole;
function logSelectedRole() {
console.clear();
console.log("Moving Forward -- " + $scope.data.selectedRole);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="demo">
<div ng-controller="DefaultController">
<div ng-repeat="role in availableRoles">
<input type="radio" ng-model="data.selectedRole" value="role" ng-value="role" name="Roles" id="{{role}}"/> <span style="display: inline-block; line-height: 28px;">{{role}}</span>
</div>
<button ng-click="logSelectedRole()">Log to console</button>
</div>
</div>
<div ng-repeat="role in Roles">
<input type="radio" data-ng-model="Role"
data-ng-value="role"
ng-change="Value()"
name="Roles">
<span>{{role}}</span>
</div>
In controller
$scope.Value=function(){
console.log("Moving Forward--"+$scope.Role);
}
Working fine...

How to dynamically create text box when we click on a link using angularjs

I have a problem to show INPUT field when do some action.
I have BUTTON (Click here) as soon as user made a click event on button i wanted to show input field
I have done this by using jQuery.
Can any one help me in Angular.js
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.boxShow = false;
});
</script>
<div ng-app="myApp">
<div ng-controller="myCtrl">
show box
<div ng-show="boxShow">
<textarea rows="4" cols="50">text</textarea>
</div>
</div>
</div>
https://jsfiddle.net/bxwjpmaa/1/
HTML
<div class="btn btn-primary" ng-click="openTextBox();">Click Me To open text box</div>
<div ng-show="openTextBox == true">
<input type="text"/>
</div>
SCRIPT :
$scope.openTextBox = function () {
$scope.openTextBox = true;
}
please don't take scope variables and function names same
example here
$scope.openTextBox = function () {
$scope.openTextBox = true;
}
//this is not correct as per angular documentation because scope.openTextBox name already assigned to scope function,again its assigning scope variable "$scope.openTextBox = true" here u will get errors when ever u clicked div second time" TypeError: boolean is not a function" it will throw this error.so please dont use which is already assigned scope function dont assign scope variable
see this fiddle url : https://jsfiddle.net/veerendrakumarfiddle/bxwjpmaa/2/
<!DOCTYPE html>
<html>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<body>
<div ng-app="myApp" ng-controller="myCtrl">
<ol>
<li ng-repeat="element in elements">
<input type="text" ng-model="element.value"/>
</li>
</ol>
<br/>
<b>Click here to add Textbox:</b><br/><input type="button" value="New Item" ng-click="newItem()"/>
<br/>
<br/>
<b>Click here to see ng-model value:</b><br/>
<input type="button" value="submit" ng-click="show(elements)">
</div>
<script>
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
var counter=0;
$scope.elements = [ {id:counter, value : ''} ];
$scope.newItem = function(){
counter++;
$scope.elements.push( { id:counter,value:''} );
}
$scope.show=function(elements)
{
alert(JSON.stringify(elements));
}
});
</script>
</body>
</html>

Uncheck checkbox with submit - AngularJS

I am trying to uncheck checkbox with submit button. The idea is when checkbox is checked button is shown, and when button is clicked checkbox is unchecked and button is hidden.
HTML page:
<html ng-app="myApp" ng-controller="myCtrl">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js"></script>
<script src="script.js"></script>
<meta charset=utf-8 />
</head>
<body>
<div ng-repeat="foo in boxes">
<div>
<input type="checkbox" name="cb" id="cb" ng-model="show" />{{foo}}
</div>
<div ng-show="show">
<form ng-submit="submit()">
<input type="submit" name="sumbit" id="sumbit" value="Hide" />
</form>
</div>
</div>
</body>
</html>
JS:
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.boxes = ['a','b','c'];
$scope.submit = function(){
$scope.show = false;
}
});
On Plukner: http://plnkr.co/edit/z9W0w18dkgYJ3D5Q3aR2?p=preview
Thanks for any help!
The problem is that you're using a single variable to store states of 3 items yet Angular creates a scope for each context in the ng-repeat iteration. By changing show to an array and using $index to reference each of them, the show array from the main scope is passed to all three child scopes and there are no conflicts, so it works:
app.controller('myCtrl', function($scope) {
$scope.boxes = ['a','b','c'];
$scope.show = [];
$scope.submit = function(){
$scope.show = [];
}
});
HTML
<div ng-repeat="foo in boxes">
<div>
<input type="checkbox" name="cb" id="cb" ng-model="show[$index]" />{{foo}}
</div>
<div ng-show="show[$index]">
<form ng-submit="submit()">
<input type="submit" name="sumbit" id="sumbit" value="Hide" />
</form>
</div>
</div>
See it here: http://plnkr.co/edit/kfTMaLTXWtpt7N9JVHAQ?p=preview
(note sure if this is exactly what you wanted because there's no question, but it's enough to get you started)
UPDATE
And here is the version where Hide unchecks only "its own" checkbox ($scope.submit now accepts the index parameter): http://plnkr.co/edit/YVICOmQrPeCCUKP2tBBl?p=preview
You need to change the html code and simplify it as
Instead of form use simple ng-click
<div ng-show="show">
<input type="submit" value="Hide" ng-click="show = !show" />
</div>

Resources