Getting selected model in angular select directive - angularjs

I've created a directive to display dropdowns (form selects).
However I cannot find a way to mark the selected option.
html form
<div content-selects ng-model="ctrl.contentSelects.riskStatus" selection="oneWMS.riskStatusId"></div> <!-- oneWMS.riskStatusId -->
directive
function contentSelects(){
return {
restrict: 'AE',
templateUrl: '/app/Directives/contentSelects.tpl.html',
replace:true,
scope: {
ngModel: '=',
selection: '='
},
controller:function($scope){
},
link: function (scope, element, attrs) {
scope.selectedModel = scope.ngModel[attrs.selection];
scope.isChanged = function () {
//console.log("changed");
}
element.removeAttr('id');
}
};
}// end function contentSelects
This is where I don't understand: the directive template
<div class="input-group">
<select id="{{id}}">
<option value="model.refId" ng-repeat="model in ngModel track by model.refId" ng-model="ngModel[selection]" >{{model.value}} *** {{selection}} *** {{ngModel[selection]}}</option>
</select>
</div>
In the actual value, {{ngModel[selection]}} gives me exactly what I want (the target model row), but when tied to ng-model it doesn't retrieve anything :/
ng-model="ngModel[selection]"
What is wrong with it? Using curly brackets break it of course...

Your problem is because of ngModel included in option element. You should move it to select element.
Demo
<div class="input-group">
<select ng-model="selectedModel" >
<option ng-value="model" ng-repeat="model in ngModel">{{model}}
</option>
</select>
</div>
And also look at https://docs.angularjs.org/api/ng/directive/ngOptions

Related

How to add conditional add html attribute?

How to add conditionally attribute in angularjs?
For example I only want to set the multiple attribute on a <select> if my component has a binding set to true. This means if the binding is not given the multiple attribute should not exist on my <select>.
The only solution I found was with ng-if.
You can achieve this by implementing a directive (aka ng-multiple) to handle the property multiple of the select element. The following snippet implements this solution. However, you may want to control the state of your model inside this directive, once the multiple prop will produce an array of selected values, the non-multiple will produce a single object, so this may cause an issue when switching between multiple and non-multiple.
angular.module('myApp', [])
.directive('ngMultiple', function () {
return {
require: ['select', '?ngModel'],
restrict: 'A',
scope: {
multiple: '=ngMultiple'
},
link: function (scope, element, attrs, ctrls) {
element.prop('multiple', scope.multiple);
scope.$watch('multiple', function (multiple) {
if(element.prop('multiple') != multiple){
// may be would be convenient change the ngModel
// to [] or {} depending on the scenario
element.prop('multiple', multiple);
}
});
}
};
})
.controller('myController', function ($scope) {
$scope.condition = true;
$scope.myOptions = [];
});
angular.element(document).ready(function () {
angular.bootstrap(document, ['myApp']);
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.8/angular.min.js"></script>
<div ng-controller="myController">
<label>
<input type="checkbox" ng-model="condition" /> multiple?
</label>
<br>
<select ng-multiple="condition" ng-model="myOptions">
<option>Option 1</option>
<option>Option 2</option>
<option>Option 3</option>
<option>Option 4</option>
<option>Option 5</option>
</select>
<br>
<tt>myOptions: {{ myOptions }}</tt>
</div>
if boolean condition is true then multiple, else not
<select ng-if="condition" ng-model="some.model" multiple></select>
<select ng-if="!condition" ng-model="some.model"></select>
<select ng-show="condition" ng-model="some.model" multiple></select>
<select ng-hide="condition" ng-model="some.model"></select>
controller,
$scope.condition = true

Reusing a directive template for multiple forms with isolated scope

I'm working on a project where the user needs to be able to create many instances of the same form. As of now the user can click a button to create one or more forms. The problem I'm having is that by isolating the scope, as I think I should be doing given that I'm reusing the same directive, my ng-models can't communicate with the parent controller.
My directive for <rule-form></rule-form>..
(function(){
'use strict';
var ruleForm = function(){
return{
restrict: 'E',
replace: true,
scope: {},
templateUrl: 'edit/rule-create/ruleForm.html',
link: function(scope, element, attrs){
scope.length = document.forms.length;
}
}
}
angular.module('ganeshaApp')
.directive('ruleForm', ruleForm)
})();
And my template...
<form class="edit__div--rule-form" name="form_{{length}}">
<input type="text" placeholder="Rule Title" ng-model="rcCtrl.ruleTitle">
<div class="edit__div--rc-toolbar">
<select class="edit__btn--rc-select" ng-model="rcCtrl.select" apply-statement-type>
<option value="obligation statement">obligation statement</option>
<option value="prohibition statement">prohibition statement</option>
<option value="permission statement">restricted permission statement</option>
</select>
<div class="edit__btn--rc-noun">
Add noun/verb
</div>
<div class="edit__btn--rc-save" ng-click="rcCtrl.saveRule()">
<span class="glyphicon glyphicon-floppy-saved"></span>Save
</div>
<div class="edit__btn--rc-cancel">
<span class="glyphicon glyphicon-remove"></span>
Cancel
</div>
</div>
<div class="edit__select--statement-type"></div>
<div ng-show="rcCtrl.showTextEdit" class="edit__div--rule-form-text" contenteditable="true" ng-model="rcCtrl.ruleText"></div>
I tried using $parent , (e.g. $parent.rcCtrl.ruleText), but then I'm back to the problem of not having isolated scopes and each form updates the others. I'm a bit confused about this really. Does anyone know a solution to this problem, or is it just a problem with my code?
Add a controller to your directive.
angular.module('ganeshaApp').directive('ruleForm', function(){
return {
restrict: 'E',
replace: true,
scope: {},
templateUrl: 'edit/rule-create/ruleForm.html',
controller: "rulesFormController as rcCtrl",
link: function(scope, element, attrs){
scope.length = document.forms.length;
}
}
});
The AngularJS $compile service will then create an instance of the controller for each instance of the directive and attach it to each isolate scope.
For more information, see the AngularJS Comprehensive Directive API Reference.

Angularjs Transclude element with ng-options

I got a directive with transclude: element and i want to apply a template to a select element with ng-options, to wrap the select with the given template.
app.directive("ngSelect", function(){
return {
restrict: "A",
replace:true,
transclude: 'element',
templateUrl: function(elem,attrs) {
return 'select.html';
},
...
compile: function compile(cElement, cAttrs, cTransclude) {
return{
pre: function preLink(scope, aElement, aAttrs, aController){
},
post: function postLink(scope, aElement, aAttrs, aController){
}
}
Usage:
<select ng-select ng-label="Select 2" ng-model="data.select2" required ng-options="item.id as item.value for item in list"></select>
But for some reason what's beeing wrapped are the options from the ng-options and not the select itself, as you can see in the final DOM here.
<div class="col-xs-12 col-sm-6 col-md-3 col-lg-2 ...">
<option value="?"selected="selected"></option>
<option value="number:1" label="value1">value 1</option>
<option value="number:2" label="value 2">value2</option>
<option value="number:3" label="value 3">value</option>
</div>
I think the select element is removed at some point of the transclusion, but i'm not realy sure. All i found about ngOptions with tranclude: element was a bit confusing.
How can i get this select to work properly with tranclude: element and ngOptions? Can i do something in the compile/pre/post link functions?
Plunker.

Calling custom directive form controller

I have written a custom directive to load 3 drop downs and handle the change event of the drop down inside the controller. On change of the dropdown value I am getting the changed value inside my controller function. I need to call my custom directive and pass the new value.
I am new to AngularJs custom directive. Please let me know how to invoke a directive from within the controller.
The view where I render the custom directive:
<div class="container">
<div class="main-header clearfix">
<div class="page-title">
<h3 class="no-margin">Search for a Host</h3>
</div>
<!-- /page-title -->
</div>
<div class="padding-md">
<div class="hostsFilters row">
<select ng-model="BU" ng-change="changeTheView()" class="form- control">
<option value="">BU</option>
<option value="1">BU1</option>
<option value="2">BU2</option>
<option value="3">BU3</option>
<option value="4">BU4</option>
</select>
<span>OR</span>
<select ng-model="Application" ng-change="changeTheView()" class="form-control">
<option value="">Application</option>
<option value="1">App1</option>
<option value="2">App2</option>
<option value="3">App3</option>
<option value="4">App4</option>
</select>
<span>OR</span>
<input type="text" class="form-text" ng-model="hostName.host_name" placeholder="Hostname">
</div>
</div>
<div class="row">
<i-data-grid></i-data-grid>
</div>
The code of my controller:
'use strict';
angular.module('angularFullstackApp')
.controller('MainCtrl', function ($scope) {
$scope.changeTheView=function(){
console.log('Came inside the Change the view function..');
//Now invoke the custom directive.
}
});
The code for my directive:
'use strict';
angular.module('angularFullstackApp')
.directive('iDataGrid', function () {
return {
templateUrl: 'app/iDataGrid/iDataGrid.html',
restrict: 'E',
link: function (scope, element, attrs) {
$(document).ready(function() {
$('#example').dataTable();
} );
}
};
});
You could take a use of attribute, & pass the values inside attribute for which you wanted to place a watch that would fire when any of the value changed
Markup
<i-data-grid watch-values="['BU', 'Application']"></i-data-grid>
Code
'use strict';
angular.module('angularFullstackApp')
.directive('iDataGrid', function () {
return {
templateUrl: 'app/iDataGrid/iDataGrid.html',
restrict: 'E',
link: function (scope, element, attrs) {
$(document).ready(function() {
$('#example').dataTable();
scope.$watch(attrs.watchValues,function(newVal, oldVal){
//newly changed value available here with same sequence
//as you passed ['BU', 'Application'] here, it fires fn when any of value changed,
//newVal[0] contains newly changed value of BU
//& newVal[1] will contain newly changed value of Application
//call what ever code on basis of this values
},true);
});
}
};
});

Angular directive ng-repeat to generate pair of elements input+span

Here is my request, using directive I try to generate this structure above :
<div class='myClass'>
<input id="id0" name="name0" type="radio" checked>
<label for="id0" ng-click="myAction('0')"> 0</label>
<input id="id1" name="name1" type="radio">
<label for="id1" ng-click="myAction('1')"> 1</label>
<input id="id2" name="name2" type="radio">
<label for="id2" ng-click="myAction('2')"> 2</label>
...3,4,5...
span(class="endSpanClass")
Not very trivial:
I have tried using directive in many ways, ng-repeat but no success to get this pair of input/label together, I mean input+label in same order as in this example.
Then on first element, I expect to get "checked" attribute.
The last span has to be set at the end also.
That kind of try
.directive('myDirective', ['$timeout', function(timeout) {
return {
restrict: 'A',
controller: 'MyController',
scope: {myList: '='},
template: '<input id="id0" name="view" type="radio">' +
'<label for="id0" ng-click="myAction(\'day\'> 0 </label>',
transclude: false,
replace: true,
link: function($scope, element, attr, ctrl) {
}
};
}])
And my directive call
div(class='myClass')
input(my-directive, my-list='list', ng-repeat="item in list", id="0", name="name0", type="radio")
Gives nothing,
If you can help and gives me some advices, thanks.
J.
Following is what I would do:
<label ng-repeat="name in names">
<input name="{{name}}" type="radio"
ng-checked="$index==0"
ng-click="myAction($index)"/>
{{$index}}
</label>
wrapping form control by label which would simplify the code
also make very explicit what label control what control.
(just a standard html technique.)
use ng-checked to control checked state.
I would avoid using directive for this short code unless
it is used many times in many places.
if you use directive, template has to have single root element.
(so you can actually resort to technique [1] above.)
Here is a simple directive definition:
app.directive('myDirective', ['$timeout', function(timeout) {
return {
restrict: 'E',
scope: {id: '='},
template: '<div><input id="id{{id}}" name="view" type="radio">' +
'<label for="id{{id}}" ng-click="myAction(\'{{id}}\')">{{id}}</label></div>',
replace: true
};
}])
Along with a working example: http://plnkr.co/edit/spQRs5xs43P1FOX7YQzH?p=preview

Resources