Having trouble setting clearing input field AngularJS - javascript

Having trouble setting clearing input field
I’m currently trying to clear the input box on ng-model="newInstruction.instructionText" after an new instruction text has been added. Here is the code where I tried to reset it to empty string but input field didn't clear. Why is that?
I’ve tried console logging the following in updateInstructionText function:
Console.log (newInstruction) returns undefined in console.
Console.log ($scope.newInstruction) returns undefined in console.
Console.log (instruction) returns a object with instruction text inside ex: Object {instructionText: ‘new instruction’}
Controller:
angular.module('app').controller('InstructionController', function($scope, $http, NgTableParams, $filter) {
$scope.initList = function() {
$scope.getRemoteInstructions = function(typed) {
$http.get("/api/instructions?searchInstructionText=" + typed).then(function(response) {
$scope.instructionChoices = _.map(response.data, function(instruction) {
instruction.instructionText;
});
});
};
$scope.updateInstructionText = function(instruction) {
var instructionPromise;
if (instruction.id) {
instructionPromise = $http.put("api/instructions/" + instruction.id, instruction);
}
else {
instructionPromise = $http.post("/api/instructions", instruction);
}
$scope.newInstruction = '';
$instruction = '';
instructionPromise.then(function(response) {
$('#instructionModal').closeModal();
$scope.instructionTable.reload();
});
};
};
});
HTML
<div class="container-fluid" ng-init="initList()">
<div class="row">
<h3>Total Instructions: {{totalInstructions}}</h3>
<table class="striped highlight bordered" ng-table="instructionTable" show-filter="true">
<tr>
<td class="input-field">
<input placeholder="Enter New Instruction Text" ng-model="newInstruction.instructionText" type="text">
</td>
<td>
<a class="waves-effect waves-light btn" ng-click="updateInstructionText(newInstruction)">Add</a>
</td>
</tr>
</table>
</div>
</div>
<ng-include src="'/views/modals/instructionModal.html'"></ng-include>
</div>

Simply do:
instruction.instructionText = null
Since you are accessing the argument (object) inside the function with name instruction, if you set this to null, you can clear the input field

Simply do
$scope.newInstruction.instructionText=null

Related

passing data from clicked item to controller in AngularJS

I am attempting to follow a JSFiddle, where a user can click on a <td> item, edit it, then eventually be able to save the changes.
The example uses ng-repeat and all others I have looked at do to where as I am not, I am using data passed from a resolve command in my route folder.
$stateProvider
.state('app.patents.patent', {
url: '/{patentId}',
component: 'patent',
resolve: {
patent: ['patents', '$stateParams', function(patents, $stateParams) {
return patents.find(function(patent){
return patent.id == $stateParams.patentId;
})
}]
}
})
}]);
I have attempted to use data-id (looked at How to retrieve the clicked ElementId in angularjs?), but with no success, as I assume you cannot use the same id twice and my desired functionality requires two elements that ng-show and ng-hide depending on the boolean value passed to them.
I have now got myself in a confused state, not sure which approach to take.
Question
How do I adapt my code that doesn't use ng-repeat to work with this JSFiddle? OR do you know another apporach I can take to achieve the same results?
<tr>
<th class="text-xs-right">Short Name</th>
<td>
<span data-id="123" ng-hide="$ctrl.shortTitle.editing" ng-dblclick="$ctrl.editItem(123)">{{$ctrl.patent.shortTitle}}</span>
<input type="text" data-id="123" ng-show="$ctrl.shortTitles.editing" ng-blur="$ctrl.doneEditing(123)" ng-model="$ctrl.patent.shortTitle"></input>
</td>
</tr>
angular.module('myApp').component('patent', {
templateUrl: 'p3sweb/app/components/patents/views/patent-item.htm',
controller: function() {
var vm = this;
vm.editItem = function (item) {
item.editing = true;
}
vm.doneEditing = function (item) {
item.editing = false;
};
});
As per my understanding regarding your question I have created a jsfiddle, have a look or you can create a jsfiddle with the issue you are facing for better understanding
JSFiddle
<!DOCTYPE html>
<div ng-app ng-controller="myCtrl" class="container">Double-click on the items below to edit:
<button type="button" ng-click="newItem()">Add item</button>
<table>
<tr ng-repeat="item in items">
<td>
<span ng-hide="item.editing" ng-dblclick="editItem(item)">{{item.name}}</span>
<input ng-show="item.editing" ng-model="item.name" ng-blur="doneEditing(item)" autofocus />
</td>
</tr>
</table>
</div>
You can create an array and connect each input to a specific index starting from 0 and then pass that index to your function call.
<tr>
<th class="text-xs-right">Short Name</th>
<td>
<span ng-hide="$ctrl.editing[1]" ng-dblclick="$ctrl.editItem(1)">{{$ctrl.patent.shortTitle}}</span>
<input type="text" data-id="123" ng-show="$ctrl.editing[1]" ng-blur="$ctrl.doneEditing(1)" ng-model="$ctrl.patent.shortTitle"></input>
</td>
</tr>
angular.module('myApp').component('patent', {
templateUrl: 'p3sweb/app/components/patents/views/patent-item.htm',
controller: function() {
var vm = this;
vm.editing=[];
vm.editItem = function (index) {
vm.editing[index] = true;
}
vm.doneEditing = function (index) {
vm.editing[index] = false;
};
});
Demo: http://jsfiddle.net/F7K63/381/

will angular update one `ng-model` inside a <tfoot>

I'm doing angular table filter. My first attempt is to try to include it on the header. The icon show on the wrong position and when I focus the text box the sorting change.
So I move the box to the <tfoot> but it looks like it is somehow disabled because even when I change the content on text box the ng-model="filter_id" it doesnt change.
The outside text box, works perfect.
In the picture:
press 1 on <tfoot input text>: the textbox change to 1, event updateFilteredList trigger but filter_id is empty, neither <p input text> nor {{filter_id}} change.
press 1 again on <tfoot input text>: the textbox change to 11, same behaviour
press 1 on <p input text>: the textbox change to 1, {{filter_id}} update to 1 and updateFilteredList also receive filter_id=1 (even when filter for 1 return the same list);
EDIT
I found out when app start if I type on the external text box the interal get updated. But when I type a single char on the internal one, stop the updates.
<div ng-controller="eventCtrl">
<table class="table table-striped" at-table at-list="filteredList"
at-config="config" at-paginated>
<thead></thead>
<tfoot>
<tr>
<th><input type="text" ng-change="updateFilteredList()"
ng-model="filter_id" style="width: 50px" />
</th>
</tr>
</tfoot>
<tbody></tbody>
</table>
<at-pagination at-config="config" at-list="filteredList"></at-pagination>
<p>
<input type="text" ng-change="updateFilteredList()"
ng-model="filter_id" />
{{filter_id}}
</p>
</div>
I'm using this plug-in for my table. Is this a bug or maybe is some behaviour of the plugin? Is there a way to detect if plug-in overwrite some events?
Controller:
app5.controller('eventCtrl', ["$scope", "$filter", "$http" , function ($scope, $filter, $http) {
$scope.cars = [
{ Car_ID: 1, X: null, Y: null, RoadName: null, Azimuth: null, DateTime: null, Adress: null }
];
$scope.filteredList = $scope.cars;
$scope.filter_id = "";
$scope.updateFilteredList = function () {
console.log('filter_id: ' + $scope.filter_id);
$scope.filteredList = $filter("filter")($scope.cars, $scope.filter_id);
console.log('filteredList.length:' + $scope.filteredList.length);
};
Probably there is a better way, but this is working. Because the event was already triggering, I just get the value from the DOM before run the filter
$scope.filter_id = $('#filter_id').val();
Function
$scope.updateFilteredList = function () {
$scope.filter_id = $('#filter_id').val();
console.log('filter_id: ' + $scope.filter_id);
$scope.filteredList = $filter("filter")($scope.cars, $scope.filter_id);
console.log('filteredList.length:' + $scope.filteredList.length);
};

AngularJS and XML, how to render it?

I am working along DB guys, they are sending me the data thru XML, and depending the kind of element they specify is what I need to display in the view.
The code you will see is a dynamic table
<table>
<thead>
<tr>
<th ng-repeat="column in cols">
<span>{{column}}</span>
</th>
</tr>
</thead>
<tbody>
<tr ng-repeat="row in rows">
<td ng-repeat="column in cols"
ng-init="isXX = column.indexOf('XX') === 0">
<span ng-if="!isXX">{{row[column]}}</span>
<button ng-if="isXX" class="btn btn-xs btn-blue"
ng-click="fillOpen()">
{{column.substring(3).replace('_', ' ')}}
</button>
</td>
</tr>
</tbody>
</table>
and here is what I have in the controller
ReportsFactory.pendingBets(reportParam).then(function(data) {
if (data.length) {
gridInfo = _.forEach(data, function(item) {return item;});
$scope.rows = gridInfo;
$scope.cols = Object.keys($scope.rows[0]);
}
}
as you can see here I have this ng-init
ng-init="isXX = column.indexOf('XX') === 0" where I am telling the app, if the property I am receiving comes with XX at the index, then display a button <button ng-if="isXX" ng-click="fillOpen()">...</button> but so far, I have some more props coming with XX at the beginning, so I need to do it more dynamic.
This is how my view looks so far
what I need to know, is how to read that XML, this is the XML printed in the Nodejs terminal
[{ BET: 57635034,
CUSTOMER: 181645,
SPORT: 'NFL',
'XX_FILL OPEN': '<element><element_type>WAGER_ACTION_BUTTON</element_type><element_call>fillOpen(57635034)</element_call><element_content/></element>',
XX_VIEW: '<element><element_type>BASIC_DROPDOWN</element_type><element_call>callThisFunction()</element_call><element_content><li>1</li><li>2</li><li>3</li><li>4</li></element_content></element>',
XX_CANCEL: '<element><element_type>BASIC_CHECKBOX</element_type><element_call/><element_content>1</element_content></element>'
}]
so, the first says
'XX_FILL OPEN': '<element><element_type>WAGER_ACTION_BUTTON</element_type><element_call>fillOpen(57635034)</element_call><element_content/></element>'
WAGER_ACTION_BUTTON should be a button
the second one says
BASIC_DROPDOWN that should be a dropdown and so on, so, how should I do in order to display the proper HTML element depending on what the XML says ?
Any suggestions ?
if I understood you correctly you want to dynamically render the xml or html content to your view... I assume that element and element type are directive you have or something.
use
ngBindHtml
e.g:
<div class="col-xs-offset-1 m-r-offset-8 p-t-offset-2 font-l-16">
<span mathjax-bind ng-bind-html="question.question.body"></span>
</div>
or you might need to use the trustAsHtml function
<div class="col-xs-offset-1 m-r-offset-8 p-t-offset-2 font-l-16">
<span mathjax-bind ng-bind-html="trustAsHtml(question.question.body)"></span>
</div>
$scope.trustAsHtml = function (val) {
return $sce.trustAsHtml(val);
};
this will take your string xml (html) code and render it...
you could always build a personalize directive and use $compile as well like:
app.directive('ngHtmlCompile',function ($compile) {
return function(scope, element, attrs) {
scope.$watch(
function(scope) {
// watch the 'compile' expression for changes
return scope.$eval(attrs.ngHtmlCompile);
},
function(value) {
// when the 'compile' expression changes
// assign it into the current DOM
element.html(value);
// compile the new DOM and link it to the current
// scope.
// NOTE: we only compile .childNodes so that
// we don't get into infinite loop compiling ourselves
$compile(element.contents())(scope);
}
);
};
});
and in the code just call the ng-html-compile... no need for $sce

How to pass focus to a new field as soon as it appears (angular 1.4)?

In the following example a new field is added (by adding a blank row to $scope) when the last field loses focus if it is not empty. The problem is that the new field is not added to the DOM in time to receive focus.
Is there a way to detect when angular has finished appending new field to the DOM and then pass focus to it?
Please, no "timer" solutions; the time it takes to change DOM is unknown and I need this focus switch to happen as fast as possible. We can do better!
JSFiddle
HTML
<div ng-app='a' ng-controller='b'>
<input type="text" ng-repeat="row in rows" ng-model="row.word" ng-model-options="{'updateOn': 'blur'}">
</div>
JS
angular.module('a', []).controller('b', function ($scope) {
$scope.rows = [{'word': ''}];
$scope.$watch('rows', function (n, o) {
var last = $scope.rows[$scope.rows.length - 1];
last.word && $scope.rows.push({'word': ''});
}, true);
});
This is a View-concern and so should be dealt with by using directives.
One way to do so, is to create a directive that grabs the focus when it's linked:
.directive("focus", function(){
return {
link: function(scope, element){
element[0].focus();
}
}
});
and use it like so:
<input type="text"
ng-repeat="row in rows"
ng-model="row.word"
focus>
Demo
Use $timeout without specifying a number of milliseconds. It will, by default, run after the DOM loads, as mentioned in the answer to this question.
angular.module('a', []).controller('b', function($scope, $timeout) {
$scope.rows = [{
'word': ''
}];
$scope.addRow = function() {
$scope.rows.push({
'word': ''
});
$timeout(function() {
//DOM has finished rendering
var inputs = document.querySelectorAll('input[type="text"]');
inputs[inputs.length - 1].focus();
});
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app='a' ng-controller='b'>
<div ng-repeat="row in rows">
<input type="text" ng-model="row.word" ng-model-options="{'updateOn': 'blur'}"><br>
</div>
<input type="button" ng-click="addRow()" value="Add Row">
</div>

Simple $scope.$watch not called?

I have a simple table app which gets JSON data from a database. It passes the data via parameter to my app controller, which then filters the data. This works great. However, it is a lot of data (hundred thousand objects). I have search boxes that I use to try and filter the data, and when the search watch should be getting called (when someone types something in the search box), it doesn't. Am I missing something?
js:
var app = angular.module('SortingTables', ['ui.bootstrap']);
//Dependencies which are services, providers or factories must map to string types, which are then passed into the instance function
app.filter('startFrom', function () {
return function (input, start) {
start = +start; //parse to int
return input.slice(start);
};
});
app.controller('Ctrl', function ($scope, filterFilter, dataTable) {
$scope.currentPage = 1;
$scope.itemsPerPage = 25;
$scope.totalItems = 0;
$scope.predicate = '';
$scope.searchBuffer = {
$: ''
};
$scope.filtered;
//This function has sort of been abstracted...
//The purpose of this function is to delay the update so the user gets a chance to finish typing before the filter is applied.
//Newer versions of angularjs have the ng-model-options: debounce=100 but we can't use that since we have IE 8 on dev boxes
$scope.$watch('searchBuffer', function (term) {
console.log('The watch on searchBuffer was called');
$scope.filtered = filterFilter(dataTable, term);
$scope.totalItems = $scope.filtered.length;
});
$scope.pageChanged = function () {
$scope.currentRow = $scope.currentPage * $scope.itemsPerPage - $scope.itemsPerPage;
};
});
html
<div ng-app="Components" ng-controller="Ctrl">
<hr/>
<table class="table table-striped">
<tr>
<th>Technical Owner
<br />
<input type="search" ng-model="searchBuffer['Technical Owner']">
</a>
</th>
<th>Branch
<br />
<input type="search" style="width: 40px" ng-model="searchBuffer.Branch">
</a>
</th>
<th>Sub Pillar
<br />
<input type="search" ng-model="searchBuffer['Sub Pillar']">
</a>
</th>
<th>Path
<br />
<input type="search" ng-model="searchBuffer.Path">
</a>
</th>
<th>Name
<br />
<input type="search" ng-model="searchBuffer.Name">
</a>
</th>
<th>Description
<br />
<input type="search" ng-model="searchBuffer.Description">
</a>
</th>
</tr>
<tr ng-repeat="ComponetOwner in filtered | startFrom:currentPage | orderBy:predicate:reverse | limitTo:itemsPerPage">
<td>{{ComponetOwner["Technical Owner"]}}</td>
<td>{{ComponetOwner.Branch}}</td>
<td>{{ComponetOwner["Sub Pillar"]}}</td>
<td>{{ComponetOwner.Path}}</td>
<td>{{ComponetOwner.Name}}</td>
<td>{{ComponetOwner.Description}}</td>
</tr>
</table>
<pagination items-per-page="itemsPerPage" total-items="totalItems" ng-model="currentPage" ng-change="pageChanged()"></pagination>
</div>
When I type something in the search box, $watch doesn't get called. What's going on?
searchBuffer is an object. The third optional argument of $watch needs to be set to 'true' for watching objects/arrays (that is for deep watching).
Read this:
$watch an object
You can do $watchCollection which will watch all the objects within an object.
Not as deep as setting the third optional argument which is true for yout $watch function.
Here is a good blog about it: http://www.bennadel.com/blog/2566-scope-watch-vs-watchcollection-in-angularjs.htm

Categories

Resources