Angular directive add template on textbox (enter of Spacebar) - javascript

I am using angular js,My target is to show a html table on (enter of spacebar) in textbox and add the element of the table in that textbox,for that i have written a directive,but i am not sure whether i have done it in right path..Ohk i will show it in detail to be more clear
Here is my html textbox
<input type="text" helps ng-model="firstText" code="1">
<div class="col-xs-4 pull-right" helps donotapply=true></div> //Do i need this??
Here helps is my directive which binds my html to the div,here is my directive code
app.directive('helps', ['$parse', '$http','$filter', function ($parse, $http,$filter) {
return {
restrict: 'AE',
scope: true,
templateUrl: 'Table.html',
link: function (scope, element, attr) {
console.log(element);
element.bind("keypress", function (event) {
if (event.which === 114 || event.which === 32) {
scope.enterMe = function () { // this is to add data to Table
scope.newArray = [
{'code' :1,'name' : 'name1','age' : 24},
{'code' : 2,'name' : 'name2','age' : 26},
{'code' : 3,'name' : 'name3','age' : 25}
]
};
scope.setElement = function (element) { // Here set element function is to add my table name to textbox
var modelValue = tempattr.ngModel + '_value';
var model = $parse(tempattr.ngModel);
model.assign(scope, element.name);
modelValue = tempattr.ngModel + '_value';
modelValue = $parse(modelValue);
modelValue.assign(scope, element.code);
};
}
}
});
}
}
}]);
And Now here my Table.html
<div class="col-xs-4 pull-right" ng-show="hideMyMtHelpDiv">
<input type="text" ng-model="searchText" placeholder="search">
<input type="button" ng-model="gad" value="GO" ng-click="enterMe();">
<table ng-show="getTableValue" class="table table-bordered table-responsive table-hover add-lineheight table_scroll">
<thead>
<tr>
<td>
Code
</td>
<td>
Name
</td>
<td>
Age
</td>
</tr>
</thead>
<tbody>
<tr ng-repeat="test in newArray" ng-dblclick="setElement(test);">
<td>
{{test.code}}
</td>
<td>
{{test.name}}
</td>
<td>
{{test.age}}
</td>
</tr>
</tbody>
</table>
</div>
Now my question is that, my table is binded with my div as well as my input textbox; So, is there any proper way to do this?
If my question is still unclear kindly comment.
Thank you for any help
Check my plunker here https://plnkr.co/edit/lAUyvYKp1weg69CsC2lg?p=preview
and read README

First of all you are using the save directive in both input and div. You can separate those as first step:
mod.directive('onKeydown', function() {
return {
restrict: 'A',
scope: {
setShowSearch: '&'
},
link: function(scope, elem, attrs) {
elem.on('keydown', function(event){
if (event.which === 114 || event.which === 32) {
setShowSearch()(true);
}
});
}
};
});
Then you can pass a function to set your showSearch variable to that directive and use that on your input:
<input type="text" ng-model="firstText" hpcode="1" on-keydown="" set-show-search="setShowSearch"/>
Now that setShowSearch is living in your controller not your directive so it has its own scope.
myApp.controller('MyController', ['$scope', function($scope) {
$scope.setShowSearch = function(show) {
//do whatever you want here
};
$scope.msg = 'This Must Work!';
}]);
Once done you now have a clean directive which is responsible for showing the table and the rest is just passing that array down to that directive in a similar way.
Hope this helps.

Related

select ng-change in table

I have been looking for answer for this but cannot find any where.
I have table which has select and date input
<table id="tblCorrAction" class="table table-bordered table-striped table-hover table-condensed">
<thead>
<tr style="height: 30px; background-color: #aeccea; color: #555; border: solid 1px #aeccea;">
<th style="width:18%;">RArea</th>
<th style="width:37%;">P</th>
<th style="width:20%;">C</th>
<th style="width:25%;">CAction</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="ca in CASelectList">
<td>{{ca.QT}}</td>
<td>{{ca.CAPT}}</td>
<td>
<select name="caC_{{ca.QuesID}}" ng-model="item" class="form-control"
ng-selected="ca.Corrected" ng-required="true"
ng-change="GetCorrectedCAData(ca, item)"
ng-options="corr as corr.caText for corr in correctedOption">
<option value="">--Select--</option>
</select>
</td>
<td>
<span>
<input name="caDate_{{ca.QuesID}}" type="text" datepicker=""
ng-model="ca.caDate"/>
</span>
</td>
</tr>
</tbody>
</table>
In my controller
$scope.correctedOption = [{ caValue: 1, caText: 'Yes' }, { caValue: 2, caText: 'No' }];
So now what I am trying to do is if use selects yes in select option then user can enter value in datetime input and if if user selects no the entered value should be reset. I tried few things, none of it worked
First :
$scope.GetCorrectedCAData = function (ca, item) {
if (item.caValue === 2) {
$scope.ca.caDate = ""
}
}
this did not work. Error : Cannot set property 'caDate' of undefined
at ChildScope.$scope.GetCorrectedCAData
2nd : Added id to input
<input id="caDate_{{ca.QuesID}}" name="caDate_{{ca.QuesID}}" type="text" datepicker=""
ng-model="ca.caDate"/>
And in controller
if (item.caValue === 2) {
angular.element(document.querySelector("#caDate_" + ca.QuesID)).val("");
}
this also did not work. Error:Missing instance data for this datepicker
3rd: looping through CASelectList a splice the row and add the spliced row with empty data for date. I do not want to use this as there can be many many many records.
Datepicker directive
ngControlMod.directive('datepicker', function () {
return {
require: 'ngModel',
link: function (scope, el, attr, ngModel) {
$(el).datepicker({
onSelect: function (dateText) {
scope.$apply(function () {
ngModel.$setViewValue(dateText);
});
}
});
}
};
});
The ca in the ng-repeat is not the same ca as in $scope.ca in the controller. When you are doing $scope.ca it means that the controller has a $scope variable called ca on it. Like this,
var Controller = function($scope) {
$scope.ca = {
caDate: "some date";
}
}
You get that Error : Cannot set property 'caDate' of undefined because $scope.ca doesn't exist on the $scope.
If you want to reference the value inside each CASelectList in the ng-repeat (Which I think you want) then you just drop the $scope. in front of ca. So your code will look like this,
var Controller = function($scope) {
$scope.GetCorrectedCAData = function (ca, item) {
if (item.caValue === 2) {
ca.caDate = ""; // This will change the ca value of the certain ca in CASelectList
}
}
}

angular directive highlight if any of inputs in div has focus

I have created an angular directive for a repeatable section with form elements
I want the whole section/div to be highlighted when any of then input fields inside the div are in focus
template.html
<div class="col-md-12 employee-section">
<label for="name_{{$index}}">Name</label>
<input type="text" id="name_{{$index}}" class="col-md-6" ng-model="model.name"/>
<label for="address_{{$index}}">Address</label>
<input type="text" id="address_{{$index}}" class="col-md-6" ng-model="model.address"/>
</div>
directive
angular.module('test').directive('employee' , function(){
return {
link: function(scope, element){
},
restrict: 'AE',
scope: {
model: "="
},
templateUrl: 'template.html'
};
}
controller
angular.module('test').controller('employeeCtrl' , function($scope){
$scope.employees = [{name:'Jackk',address:'Main st'}, {name:'Jill',address:'Main st 123'}
});
html page
<div ng-repeat="employee in employees>
<employee model="employee"></employee>
</div>
Here's the directive which I was looking for with link for Plnkr
app.directive('ngFocusModel', function () {
return function (scope, element) {
var focusListener = function () {
scope.hasFocus = true;
scope.$digest();
};
var blurListener = function () {
scope.hasFocus = false;
scope.$digest();
};
element[0].addEventListener('focus', focusListener, true);
element[0].addEventListener('blur', blurListener, true);
};
});

How to track behavior of ngModel array item using .directive

Hi everyone I'm use angularjs not so long time ago and now I have one issue related with this framework that i can't to solve. So the problem in next: I have few input fields that generate via ng-repeat:
<div class="form-group" ng-repeat="(i, name) in name_list track by $index">
<div class="row">
<div class="col-xs-12">
<input class="form-control" type="text" ng-model="data.name_list[i]" add-input/>
</div>
</div>
Where name_list some array with data. As result I have generated input fields. Next that i wanted to do it's adding new input field if all previously fields was $dirty for this thing i wrote next angular code:
userApp.directive('addInput', ['$compile', '$sce', function ($compile, $sce) {
return {
restrict: 'A',
require: '?ngModel',
link: function (scope, element, attrs, ngModel) {
scope.inputCounter = scope.name_list.length;
scope.$watch(
function(){
return ngModel.$dirty
},
function(dirty_val){
if (dirty_val){
scope.name_list.push(ngModel.$modelValue);
}
}
);
}
}}]);
but of course this code works wrong (it add new field if at last one field is $dirty) I know why it works wrong but I do not know how to track all ng-models separate, I don't know how to get access to some model like ngModel[1],so I hope somebody will help me in this, thank's
You could add a parent directive which will collect the dirty elements, and will add new element once it detects all of the other elements are dirty:
Check this plunker.
HTML:
<div collect-input>
<div class="form-group" ng-repeat="(i, name) in name_list track by $index">
<div class="row">
<div class="col-xs-12">
<input class="form-control" type="text" ng-model="data.name_list[i]" add-input/>
</div>
</div>
</div>
Once addInput detects it is dirty, call parent directive controller:
if (dirty)
collectInput.reportInput();
JS:
directive('collectInput', function() {
return {
restrict: 'A',
controller: function($scope) {
var dirtyCount = 0;
this.reportInput = function() {
var count = $scope.name_list.length;
dirtyCount++;
if (count === dirtyCount) {
$scope.name_list.push('aaa');
}
}
},
}
}).
directive('addInput', ['$compile', '$sce', function ($compile, $sce) {
return {
restrict: 'A',
require: ['^collectInput', '?ngModel'],
link: function (scope, element, attrs, ctrls) {
var collectInput = ctrls[0]
var ngModel = ctrls[1];
scope.inputCounter = scope.name_list.length;
scope.$watch(
function(){
return ngModel.$dirty
},
function(dirty_val){
if (dirty_val){
collectInput.reportInput();
}
}
);
}
}}]);

inject HTML when enter key pressed on input

I have an input field and when people press enter I'd like the field to be emptied and its value printed below with an 'x' icon to delete it afterwards just like the 'search' field on angel.co: https://angel.co/jobs
Here is my HTML:
<form ng-submit="searchAds(searchInput)">
<input id="search-field" type="search" placeholder="Start typing your search..." ng-change="searchRequest()" ng-model="searchInput"/>
</form>
<div id="search-tags"></div>
And my JS in my controller:
$scope.searchAds = function(item){
if (item === "") return;
$scope.searchInput = "";
$('#search-tags').append('<div ng-show="showDetails">' + item + '<div ng-click="showDetails = ! showDetails"> (my DVG icon here) </div></div>');
}
I have 2 problems here:
1 - I believe the code is not compiled when printed so the 'ng-show' and 'ng-click' are so working - how can I make this work?
2 - How can I make sure that when there are several tags, when clicking on my delete icon it hide only this specific tag?
Many thanks
Why not angular instead of jQuery?
You can add a directive to manage the "enter" key:
angular.module('yourModule').directive(
'ngEnter',
function () {
'use strict';
return function (scope, element, attrs) {
element.bind("keydown keypress", function (event) {
if(event.which === 13) {
scope.$apply(function (){
scope.$eval(attrs.ngEnter);
});
event.preventDefault();
}
});
};
});
And then change a bit your code:
<form ng-submit="searchAds(searchInput)">
<input type="search" placeholder="Start typing your search..." ng-enter="add(searchInput)" ng-model="searchInput"/>
</form>
<div ng-repeat="tag in tags">
<div>{{tag}}<div ng-click="delete(tag)">(my DVG icon here)</div></div>
</div>
Your controller:
$scope.add = function(item) {
$scope.tags.push(item);
$scope.searchInput = "";
}
$scope.delete = function(item) {
var index = $scope.tags.indexOf(item);
$scope.tags.splice(index, 1);
}

Autocomplete with min Length angularjs

I am using in my application angular.js and html. So, I would like to autocomplete a textbox,but only when the length of the field "UserSearch" is greater than 3.
MY HTML
<div class="col-sm-8">
<div class="input-group">
<input data-ng-model="UserSearch" ng-change="selectSearchType(UserSearch)" list="title" type="text" class="form-control" placeholder="Name to search">
<span class="input-group-btn">
<button class="btn btn-primary" type="button"><i class="glyphicon glyphicon-search"></i></button>
</span>
<datalist id="{{test}}">
<option data-ng-repeat=" user in AllUser" value="{{user.name}}">
</datalist>
</div>
</div>
MY JS
$scope.test = "";
$scope.selectSearchType = function (UserSearch) {
if (UserSearch.length > 3) {
$scope.test = "title";
$http.get("/api/getAllUser?SearchUser=" + UserSearch).success(function (data) {
$scope.AllUser = data;
})
}
else {
$scope.test = "";
}
}
I still have the same problem.. When i type a name in the field, two names appears in the datalist, but when I click on the triangle on the top of the texbox, all data appears... What can I do to fix this problem ?
If you're using the HTML5 datalist, then in essence you're rolling your own autocomplete.
What I would recommend, is to create a directive that encapsulates your above code.
So this:
<div class="input-group">
<input data-ng-model="UserSearch" ng-change="selectSearchType(UserSearch)" list="title" type="text" class="form-control" placeholder="Name to search">
<span class="input-group-btn">
<button class="btn btn-primary" type="button"><i class="glyphicon glyphicon-search"></i></button>
</span>
<datalist id="{{test}}">
<option data-ng-repeat=" user in AllUser" value="{{user.name}}">
</datalist>
</div>
Turns into this:
<autocomplete
search="UserSearch"
on-select="selectSearchType"
min-search="3"
list="user in AllUser">
</autocomplete>
The basic directive looks like this:
var app = // get your angular module
app.directive('autocomplete', function () {
return {
replace: true,
restrict: 'E',
scope: {
search: "=",
minSearch: "=",
list: "=",
onSelect: "="
},
templateUrl: 'template/autocomplete-template.html', // use the above template
link: function (scope, el, attrs) {
scope.$watch('UserSearch', function() {
if(scope.search.length > scope.minSearch) {
// this onSelect function will callback
// into your controller
scope.onSelect(search);
}
});
}
}
});
You can now call into your controller to make your AJAX call. This callback will allow you to use the component in different places in your project.
As #Rich comments, it's not certain what the problem seems to be. However, check this fiddle. It uses $scope.$watch to watch for changes in UserSearch, firing a request through $http if the text is longer than 3 characters.
$scope.$watch('UserSearch', function(UserSearch) {
if (UserSearch && UserSearch.length > 3) {
$http.get('/api/getAllUser?SearchUser=' + UserSearch).success(function(users) {
$scope.AllUser = users;
}).error(function() {
$scope.AllUser = [{name: 'test'}, {name: 'example'}];
});
}
});

Categories