AngularJS apply select2 on element within modal - angularjs

I'm trying to apply select2 on a select element within a modal.
The modal is defined as a script ng-template. This works fine if it's not a modal (or a template).
<script type="text/javascript">
$(document).ready(function ($) {
$("#typeDescription").select2({
placeholder: 'Select a type...',
allowClear: true
});
});
</script>
However I cannot include the above code within
<script type="text/ng-template" id="myModal">
</script>
So the thing is I want to apply select2 on my element on the modal. How can I do that? How can I access the modal element by id and apply select2 on it?
EDIT:
I made some changes:
On the controller I made a function:
......
$scope.select = function() {
$(document).ready(function ($) {
$("#typeDescription").select2({
placeholder: 'Select a type...',
allowClear: true
});
});
};
and then within my template:
at the select filed (see bellow) I did like this: data-ng-init="select()"
and actually works, it applies the select2 to my element.
Is this a proper approach? Can I make use of ng-init for this case?
<script type="text/ng-template" id="myModal">
<div class="modal-header">
<button type="button" class="close" ng-click="currentModal.close();" aria-hidden="true">×</button>
<h4 class="modal-title">Title</h4>
</div>
<div class="modal-body">
<div class="form-horizontal">
<div class="form-group">
<label class="col-sm-2 control-label" for="field-1">Name</label>
<div class="col-sm-10">
<input type="text" class="form-control" data-ng-model="newType.Name" id="field-1" placeholder="Name">
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label" for="field-5">Description</label>
<div class="col-sm-10">
<textarea class="form-control" data-ng-model="newType.Description" cols="5" id="field-5" placeholder="Description"></textarea>
</div>
</div>
<div class="form-group">
<label class="col-sm-2 control-label" for="field-5">Select Type</label>
<div class="col-sm-10">
<select class="form-control" id="typeDescription" data-ng-model="newType.Type" data-ng-init="select()">
<option data-ng-repeat="item in allTypes.Types" value="{{item.Value}}">{{item.Text}}</option>
</select>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-gray btn-single" data-ng-click="currentModal.close();">Cancel</button>
<button type="button" class="btn btn-info btn-single" data-ng-click="createType(); currentModal.dismiss();">Save</button>
</div>
</script>

I would recommend that you create a directive wrapping the select2 plugin:
var lib = angular.module('lib');
lib.directive('mySelect', [function() {
var link = function (scope, element, attrs) {
element.select2({
placeholder: attrs.placeholder,
allowClear: attrs.allowClear
});
}
return {
restrict: 'A',
link: link
};
}]);
use it like this:
<select data-my-select placeholder="'Select a type...'" allowClear="true"></select>
This will initialize the select2 when the select control is rendered.

Related

ng-repeat : ng-model problem adding new element

I have I form of inputs and using ng-repeat I add new inputs fields dinamically with button.
Each input is already completed by "text".
The problem :
When I insert new input field by button, the first input field clean out text.
I verify in my browser debugger and first element of my Items Array is not empty. Why it is not present on input ?
There is my HTML:
<div class="row">
<div class="col-sm-10">
<input ng-repeat="item in vm.myItemsArray"
name="myItemName"
class="form-control"
type="text"
ng-model="item.value"/>
</div>
<div class="col-sm-1 col-sm-offset-1">
<span ng-click="addItem()" class="glyphicon glyphicon-plus btn-sm btn-default"/>
</div>
</div>
AND JS :
// INITIALIZE INPUTS
vm.myItemsArray = [{value: "text"}];
// ADD NEW INPUTS
function addItem() {
vm.myItemsArray.push({value: "text"});
}
(function() {
'use strict';
angular
.module('angularExampleModule',[])
.controller('angularExampleController', ['$scope', angularExampleController]);
function angularExampleController($scope){
$scope.myItemsArray = [{value: "text"}];
$scope.addItem = function () {
$scope.myItemsArray.push({value: "text"});
}
}
})();
.input-element{
margin:10px;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="angularExampleModule" ng-controller="angularExampleController">
<div class="row">
<div class="col-sm-10 input-element" ng-repeat="item in myItemsArray">
<input name="myItemName" class="form-control" type="text" ng-model="item.value"/>
</div>
<div class="col-sm-1 col-sm-offset-1">
<button ng-click="addItem()" class="glyphicon glyphicon-plus btn-sm btn-default">Add Item</button>
</div>
</div>
OR Check this https://codepen.io/DeepaliK/pen/BqXqNB

angularjs form inside bootstrap modal popup

I have a form inside a bootstrap modal.But I can't able to get the values of form on controller side with scope variable.
https://plnkr.co/edit/FjKXUpoBDdvQqomI97ml?p=preview
My original code has another problem also. when I click on submit button it will refresh the whole page and submit function is not executing.
My form:
<div class="modal-body">
<form class="form-horizontal" name="contact" ng-submit="contactForm()">
<div class="form-group">
<label class="col-lg-3 control-label">Name* :</label>
<div class="col-lg-8">
<input class="form-control" type="text" id="name" name="_name" ng-model="_name" > </div>
</div>
<div class="form-group">
<label class="col-lg-3 control-label">Email* :</label>
<div class="col-lg-8">
<input class="form-control" type="email" id="email" name="_email" ng-model="_email" required> </div>
</div>
<div class="form-group">
<label class="col-lg-3 control-label">Mobile* :</label>
<div class="col-lg-8 row">
<div class="col-lg-4">
<input type="text" class="form-control" ng-model="_cc" placeholder="+91" name="_cc"> </div>
<div class="col-lg-8">
<input class="form-control" type="text" ng-model="_mobile" maxlength="10" ng-pattern="/^[0-9]{5,10}$/" id="mobile" name="_mobile"></div>
</div>
</div>
<div class="form-group">
<label class="col-lg-3 control-label">Message :</label>
<div class="col-lg-8">
<textarea class="form-control" rows="2" name="_condition" ng-model="_condition"></textarea>
</div>
</div>
<div class="form-group">
<div class="col-lg-offset-7 col-lg-5">
<button type="submit" class="btn btn-primary" id="contactSubmit" >Submit</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div></div>
</form>
</div>
Controller:
$scope.contactForm = function(){
console.log($scope._condition,$scope._name,$scope._email,$scope._cc,$scope._mobile);
};
You are opening the modal using plain jQuery approach which is not going to work in Angular, because opened modal is not connected to Angular application, so it doesn't know that modal has to be handled, HTML parsed, etc.
Instead you should use directives properly, or in case of modal dialog you can simply use existent ones, like Angular UI project, which brings ready Bootstrap directives for Angular. In your case you need $modal service and inject the $http service to have your data posted.
Here is the working plunker using angular-ui bootstrap.
PLUNKER:https://plnkr.co/edit/rjtHJl0udyE0PTMQJn6p?p=preview
<html ng-app="plunker">
<head>
<script src="https://code.angularjs.org/1.2.18/angular.js"></script>
<script src="https://angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.6.0.js"></script>
<script src="script.js"></script>
<link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap-combined.min.css" rel="stylesheet">
</head>
<body>
<div ng-controller="ModalDemoCtrl">
<script type="text/ng-template" id="myModalContent.html">
<div class="modal-header">
<h3>I'm a modal!</h3>
</div>
<form ng-submit="submit()">
<div class="modal-body">
<label>Email address:</label>
<input type="email" ng-model="user.email" />
<label>Password</label>
<input type="password" ng-model="user.password" />
</div>
<div class="modal-footer">
<button class="btn btn-warning" ng-click="cancel()">Cancel</button>
<input type="submit" class="btn primary-btn" value="Submit" />
</div>
</form>
</script>
<button class="btn" ng-click="open()">Open Modal</button>
</div>
</body>
</html>
JS:
angular.module('plunker', ['ui.bootstrap']);
var ModalDemoCtrl = function ($scope, $modal, $log,$http) {
$scope.user = {
email: '',
password: null,
};
$scope.open = function () {
$modal.open({
templateUrl: 'myModalContent.html', // loads the template
backdrop: true, // setting backdrop allows us to close the modal window on clicking outside the modal window
windowClass: 'modal', // windowClass - additional CSS class(es) to be added to a modal window template
controller: function ($scope, $modalInstance, $log, user) {
$scope.user = user;
$scope.submit = function () {
$log.log('Submiting user info.'); // kinda console logs this statement
$log.log(user);
$http({
method: 'POST',
url: 'https://mytesturl.com/apihit',
headers: {
"Content-type": undefined
}
, data: user
}).then(function (response) {
console.log(response);
$modalInstance.dismiss('cancel');
}, function (response) {
console.log('i am in error');
$modalInstance.dismiss('cancel');
});
//$modalInstance.dismiss('cancel'); // dismiss(reason) - a method that can be used to dismiss a modal, passing a reason
}
$scope.cancel = function () {
$modalInstance.dismiss('cancel');
};
},
resolve: {
user: function () {
return $scope.user;
}
}
});//end of modal.open
}; // end of scope.open function
};

Angular validation directive not working properly

I am using custom angular directive for showing validation. Directive code is as below
angularFormsApp.directive('showErrors',['$timeout', function ($timeout) {
return {
restrict: 'A',
require: '^form',
link: function (scope, el, attrs, formCtrl) {
// find the text box element, which has the 'name' attribute
var inputEl = el[0].querySelector("[name]");
// convert the native text box element to an angular element
var inputNgEl = angular.element(inputEl);
// get the name on the text box so we know the property to check
// on the form controller
var inputName = inputNgEl.attr('name');
var helpText = angular.element(el[0].querySelector(".help-block"));
// only apply the has-error class after the user leaves the text box
inputNgEl.bind('blur', function () {
el.toggleClass('has-error', formCtrl[inputName].$invalid);
helpText.toggleClass('hide', formCtrl[inputName].$valid);
});
scope.$on('show-errors-event', function () {
el.toggleClass('has-error', formCtrl[inputName].$invalid);
});
scope.$on('hide-errors-event', function () {
$timeout(function () {
el.removeClass('has-error');
}, 0, false);
});
}
}
}]);
and Html is as below
<div class="container" id="login-form">
<img src="assets/img/logo-big.png">
<div class="row">
<div class="col-md-4 col-md-offset-4">
<div class="panel panel-default">
<div class="panel-heading">
<h2>Login Form</h2>
</div>
<div class="panel-body">
<form name="loginForm" class="form-horizontal" novalidate>
<div class="form-group mb-md" show-errors>
<div class="col-xs-12">
<div class="input-group">
<span class="input-group-addon">
<i class="ti ti-user"></i>
</span>
<input type="text" class="form-control" placeholder="Username" autocomplete="Off" ng-required="true" name="username" autofocus ng-model="loginUser.username">
</div>
<span class="help-block" ng-if="loginForm.username.$error.required">Username is required</span>
</div>
</div>
<div class="form-group mb-md" show-errors>
<div class="col-xs-12" >
<div class="input-group">
<span class="input-group-addon">
<i class="ti ti-key"></i>
</span>
<input type="password" class="form-control" placeholder="Password"
name="password"
ng-model="loginUser.password" autocomplete="Off"
ng-required="true">
</div>
<span class="help-block" ng-if="loginForm.password.$error.required">Password is required</span>
</div>
</div>
<div class="form-group mb-n">
<div class="col-xs-12">
Forgot password?
<div class="checkbox-inline icheck pull-right p-n">
<label for="">
<input type="checkbox"></input>
Remember me
</label>
</div>
</div>
</div>
</form>
</div>
<div class="panel-footer">
<div class="clearfix">
Register
Login
</div>
</div>
</div>
</div>
</div>
</div>
Controller code :
var loginController = function ($scope, $window, $routeParams, $uibModal, $location, $filter, $rootScope, DataService, SharedProperties) {
$rootScope.bodylayout = 'focused-form animated-content';
$scope.loginUser = {
username: "",
password:""
}
$scope.load = function () {
//getAppointmentInfo();
};
$scope.SubmitLoginForm = function () {
$scope.$broadcast('show-errors-event');
if ($scope.loginForm.$invalid)
return;
}
}
angularFormsApp.controller("loginController", ["$scope", "$window", "$routeParams", "$uibModal", "$location", "$filter", "$rootScope", "DataService", "SharedProperties", loginController]);
Now When I open form below input control validation span is displaying by default . When I click on Login button then its showing in red and working fine.
problem is it shouldn't show by default when Page is opend.. Please see image below
Instead of this
loginForm.password.$error.required
try this
(loginForm.$submitted || loginForm.username.$dirty) && loginForm.password.$error.required
Take a look at the ng-messages directive. Its fairly elegant. Example:
<form name="myForm">
<input type="text" ng-model="field" name="myField" required minlength="5" />
<div ng-messages="myForm.myField.$error">
<div ng-message="required">You did not enter a field</div>
<div ng-message="minlength">The value entered is too short</div>
</div>
</form>
You can then combine it with any form validation. Just place the error messages from the validators onto the elements $error object and they are automatically rendered in your UI.
I ended up here as part of my search for an issue. In my case I was using a directive with a changing minimum value like this:
ngOnChanges(changes: SimpleChanges) {
if (changes.minDate && this.control) {
this.control.updateValueAndValidity({ onlySelf: true });
}
}
This means that the form will not be updated, I removed onlySelf and it worked correctly.
this.control.updateValueAndValidity();
Just leaving this as a breadcrumb in case someone else does something similar.

Angular expression doesn't work with ng-disabled

<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.7/angular.js"></script>
<body ng-app="myApp">
<div ng-controller="toDoCtrl">
<div>
<hr>
<form class="form" name="commentForm" ng-submit="vm.submitCommentForm()">
<div class="form-group">
<label for="fieldBody">Comment:</label>
<textarea name="body" id="fieldBody" class="form-control" rows="3"
ng-change="vm.changeCommentForm()"
ng-model="vm.commentForm.body"></textarea>
</div>
<div class="form-group">
<button type="submit" class="btn btn-primary" ng-disabled="!vm.validCommentForm">Comment</button>
</div>
</form>
<hr>
</div>
</div>
Script
var app = angular.module('myApp', []);
app.controller('toDoCtrl', function () {
var vm = this;
vm.validCommentForm = true;
})
The "comment" button appears disabled when vm.validCommentForm = true
Meanwhile if I hardcode ng-disabled=0comment button appears working, as supposed. What did I get wrong?
You are using controllerAs methodology but not setting the alias in view
Try changing
<div ng-controller="toDoCtrl">
To
<div ng-controller="toDoCtrl as vm">

AngularJS refresh smart table after inserting new record in Bootstrap Modal Form

I use angular-bootstrap and and Angular Smart table.
I have a modal form which adds new records to database and shows the list in my smart table. Adding new records is working fine but how do I refresh my smart table after a new record is inserted into the database.
Controller
//ajax request to gather data and list in smart table
october.controllers['dashboard/feeds'] = function ($scope, $filter , $request, $modal, $log, $http) {
$scope.api = $request('onFeeds', {success: function(data, scope){
this.success(data).done(function() {
$scope.rowCollection = [];
$scope.rowCollection = angular.fromJson(data.result);
$scope.displayedCollection = [].concat($scope.rowCollection);
});
}
});
}
//Modal
var ModalInstanceCtrl = function ($scope, $modalInstance, $request, $filter) {
$scope.save = function (data) {
$request('onAddFeed',
{data:data,
success: function(data){
this.success(data);
$scope.refresh();
$modalInstance.close();
}
});
};
};
Template
<script type="text/ng-template" id="myModalContent.html">
<div class="modal-header">
<h3 class="modal-title">neue Feed eintragen!</h3>
</div>
<div class="modal-body">
<form class="form-horizontal" role="form">
<input type=hidden ng-init="formInfo.user_id = {% endverbatim %} {{ user.id }} ">
{%verbatim %}
<div class="form-group">
<label for="inputName3" class="col-sm-2 control-label">Feed Name</label>
<div class="col-sm-8">
<input class="form-control" id="inputName3" placeholder="Feed Name" ng-model="formInfo.name">
</div>
</div>
<div class="form-group">
<label for="inputEmail3" class="col-sm-2 control-label">Feed Type</label>
<div class="col-sm-8">
<select ng-model="formInfo.feed_type" class="form-control">
<option>Select Feed Source</option>
<option value="api">API</option>
<option value="xml">XML</option>
<option value="csv">CSV</option>
<option value="json">JSON</option>
<option value="upload">Upload</option>
</select>
</div>
</div>
<div class="form-group" ng-show="formInfo.feed_type =='api'">
<label for="selectAPI" class="col-sm-2 control-label">Select API</label>
<div class="col-sm-8">
<select ng-change="selectAction(item.id)" ng-model="formInfo.network_id" ng-options="item.id as item.name for item in networks" class="form-control"> </select>
</div>
</div>
<div class="form-group" ng-repeat="setup in setups">
<label for="setup" class="col-sm-2 control-label">{{setup}}</label>
<div class="col-sm-8">
<input ng-model="formInfo['api_credentials'][setup]" class="form-control" placeholder="Enter your {{setup}}">
</div>
</div>
<div class="form-group" ng-show="formInfo.feed_type =='xml' || formInfo.feed_type =='csv' ">
<label for="inputPassword3" class="col-sm-2 control-label">Source</label>
<div class="col-sm-8">
<div class="input-group">
<div class="input-group-addon"><i class="fa fa-link"></i></div>
<input ng-model="formInfo.source" type="text" class="form-control" id="sourceInput" placeholder="URL">
</div>
</div>
</div>
</div>
<span>{{formInfo}}</span>
</form>
</div>
<div class="modal-footer">
<button type="submit" class="btn btn-primary" ng-click="save(formInfo)">Save</button>
<button type="button" class="btn btn-warning" ng-click="cancel()">Cancel</button>
</div>
</script>
{data:data,
success: function(data){
this.success(data);
$scope.refresh();
$modalInstance.close();
}
In the above code Instead of $scope.refresh() use $route.reload() to
Update the records before closing Modal Instance.
reload() Causes $route service to reload the current route even if $location hasn't changed
To refresh the smart-table you can add or remove items or just recreate the array.
$scope.tableData = [].concat($scope.tableData);
The thing that worked for me (and appears to be causing you the problem) is to set displayedCollection to an empty array. Smart Table will fill it with whatever paged, filtered, or sorted data you designate. Something like this:
<table st-table="displayedCollection" st-safe-src="rowCollection">
All of a sudden, rowCollection.push(data) automatically updated the Smart Table.

Resources