I have HTML code with inline element:
<span class="title" ng-click="update()">Rock</span>
How to replace this element on input element after click for edit?
And then after push enter on input return back span element?
I tried with directives ng-hide(), ng-show(). But I wonder
You can use either
<span class="title" ng-hide="isEdited" ng-click="update()">Rock</span>
or
<span class="title" ng-show="!isEdited" ng-click="update()">Rock</span>
or even
<span class="title" ng-if="!isEdited" ng-click="update()">Rock</span>
In any case you will want to reference something that can be truthy. For example in your controller you would have something like this in your function
/*the init function just makes sure that everything is setup
and nothing caries over from any local storage or anything
else you may be using*/
init();
init function(){
$scope.isEdited = false;
}
$scope.update = function(){
$scope.isEdited = true;
}
What you need to do is set a variable that contains the state;
<html>
<body ng-app="app">
<div ng-controller="mainController as $ctrl">
<span ng-if="!$ctrl.isInEditMode" class="title" ng-click="$ctrl.update()" ng-bind="$ctrl.spanText"></span>
<div ng-if="$ctrl.isInEditMode">
<input type="text" placeholder="Value for rock" ng-model="$ctrl.spanText" />
<button ng-click="$ctrl.update()">Done</button>
</div>
</body>
</html>
angular.module('app', [])
.controller('mainController', function($scope) {
this.isInEditMode = false;
this.spanText = 'Rock';
this.update = (function() {
this.isInEditMode = !this.isInEditMode;
}).bind(this);
});
I have prepared a Codepen that shows an possible solution: http://codepen.io/stefferd/pen/QdQrrv
Related
Background:
So I am working with a modal box for searching through a list of task entries within a database using a form to narrow results. In this modal box, there is a custom radio button that's used for selecting whether or not the task is in progress (simple "Yes" or "No" option). The goal is to set the "No" option as the default value whenever the modal is called. Currently, I am using data-ng-init; however, this only works the first time the modal is opened. If the user closes the modal and reopens it, the default value is no longer set. Below is a sample of what this custom button looks like:
<div class="col-sm-6">
<div style="margin-bottom:10px">
<button type="button" data-ng-init="tr.taskInProgress('No')"
title="Task In Progress: No" data-ng-click="tr.taskInProgress('No')"
style="border:0;background:transparent">
<img src="../images/selected.png" data-ng-switch-when="No" />
<img src="../images/Deselect.png" data-ng-switch-when="Yes" />
<img data-ng-switch-when="" src="/nc/images/Deselect.png" /></button>
<text>No
</div>
(another similar button, but for 'yes')
</div>
In the accompanying .js file, the following is used to help populate this modal:
/*--------- Get Tasks ---------*/
tr.closeGetTaskModal = closeGetTasModal;
tr.displayGetTaskMessage = true;
tr.selectedStatusType = getStatusType;
tr.trackingId = '';
tr.performGetTask = performGetTask;
tr.isTaskInProgess = isTaskInProgress;
And, in the same .js file, the following function is used to modify the radio:
function isTaskInProgress(newValue) {
tr.isTaskInProgress = newValue;
}
I have been looking through others iterations on how they handle such cases, but I have been unlucky and have not found anything similar enough to what I am working with that works. I have tried setting the default in the Get Tasks section by modifying isTaskInProgress('No'), but this only locked the modal and I couldn't modify the option. I have tried setting the default inside the isTaskInProgress function; however, this only worked when the button was clicked, it failed to set a default. I tried seeing if data-ng-default would work; however, this didn't seem to be a recognized parameter. Does anyone have suggestions on how to modify this to get the desired results? Thank you all in advance for your help
Small Disclaimer
I am taking the liberty of assuming you are using UI Bootstrap (since I see bootstrap classes in your sample HTML), so will be using Uib Modal in my example.
Bootstrap Modal docs: https://angular-ui.github.io/bootstrap/#!#modal
Resolver / Callback Solution
You will most likely want to use the controller to set your tr.isTaskInProgress flag rather than using the ng-init directive (a bit more flexibility / readability).
Set tr.isTaskInProgress to false at the top of your target controller function, then pass its value to your modal as a property in a "Modal Resolve Object".
Bootstrap's explanation of the Resolve Object: https://angular-ui.github.io/bootstrap/#!#ui-router-resolves
Code
function MainController($scope, $uibModal) {
let vm = this;
vm.isTaskInProgress = false;
// When you open the modal, pass in the isTaskProgress value
let modalInstance = $uibModal.open({
templateUrl: 'myModalContent.html', // Points to the script template
controller: 'ModalController', // Points to the controller
controllerAs: 'mc',
windowClass: 'app-modal-window',
backdrop: 'static',
resolve: {
isTaskInProgress: function() {
// pass the task state to the Modal
return vm.isTaskInProgress;
}
}
});
// handle the value(s) passed back from the modal
modalInstance.result.then(returnedTaskState => {
// reassign the returned value of the modal
if (returnedTaskState !== null) {
vm.isTaskInProgress = returnedTaskState;
}
});
}
Working Example
https://plnkr.co/ryK7rG
In the interest of time, I've changed some of the variable / method names from what you have in your snippets. In the example, you can...
Set the In Progress value before you open the modal and the modal reflects the In Progress value.
Change the In Progress value inside the modal. On closing the modal, the value will be updated in the main page.
SO Snippet
I realize the SO Snippet window is not exactly the best place for this example, but just tossing my example code in here in case Plunker is inconvenient for some reason.
(function() {
"use strict";
let app = angular
.module("myApp", ["ui.bootstrap"])
.controller("MainController", MainController);
MainController.$inject = ["$scope", "$timeout", "$uibModal"];
function MainController($scope, $timeout, $uibModal) {
/**
* John Papa Style Guide
* https://github.com/johnpapa/angular-styleguide/blob/master/a1/README.md
* */
let vm = this;
// ==== scoped variables ====
vm.title = "AngularJS - Passing Toggled Values to a Modal"
vm.taskInProgress = false;
vm.taskButtonLocked = false;
// ==== functions hoist ====
vm.beginTask = _beginTask;
function _beginTask() {
vm.modalIsOpen = true;
// do work
openModal();
}
// ==== local functions ====
function openModal() {
// open the modal with configurations
let modalInstance = $uibModal.open({
templateUrl: 'myModalContent.html', // Points to my script template
controller: 'ModalController', // Points to my controller
controllerAs: 'mc',
windowClass: 'app-modal-window',
backdrop: 'static',
resolve: {
taskInProgress: function() {
// pass the task state to the Modal
return vm.taskInProgress;
}
}
});
// handle the value(s) passed back from the modal
modalInstance.result.then(returnedTaskState => {
// reset control values after modal is closed
vm.taskButtonLocked = false;
vm.modalIsOpen = false;
// reassign the returned value of the modal
console.log("returnedTaskState: ", returnedTaskState);
if (returnedTaskState !== null) {
vm.taskInProgress = returnedTaskState;
}
});
}
}
})();
(function() {
'use strict';
angular
.module('myApp')
.controller('ModalController', ModalController);
ModalController.$inject = ['$scope', '$timeout', '$uibModalInstance', 'taskInProgress'];
function ModalController($scope, $timeout, $uibModalInstance, taskInProgress) {
// Assign Cats to a Modal Controller variable
let vm = this;
vm.inProgress = taskInProgress;
console.log("taskInProgress", taskInProgress)
$scope.submit = function() {
$uibModalInstance.close(vm.inProgress);
}
$scope.close = function() {
$uibModalInstance.close(null);
}
}
})();
input[type="radio"]:hover {
cursor: pointer;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>AngularJS Plunk</title>
<link rel="stylesheet" href="style.css" />
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" integrity="sha384-BVYiiSIFeK1dGmJRAkycuHAHRg32OmUcww7on3RYdg4Va+PmSTsz/K68vbdEjh4u" crossorigin="anonymous">
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/font-awesome/4.7.0/css/font-awesome.min.css" integrity="sha384-wvfXpqpZZVQGK6TAh5PVlGOfQNHSoD2xbE+QkPxCAFlNEevoEH3Sl0sibVcOQVnN" crossorigin="anonymous">
<!-- JQuery and Bootstrap -->
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.7/js/bootstrap.min.js"></script>
<!-- Angular Stuff -->
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.8/angular.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 Angularjs App -->
<script type="text/javascript" src="app.js"></script>
</head>
<body ng-app="myApp" ng-controller="MainController as tr">
<!-- ==== MAIN APP HTML ==== -->
<div class="container" style="padding:1em;">
<div class="row">
<div class="col-xs-12">
<div class="jumbotron text-center">
<h2>{{ tr.title }}</h2>
<h4><em>SO Question #55362380</em></h4>
<h4><em>AngularJS - v1.7.8</em></h4>
</div>
</div>
<div class="col-xs-12">
<form>
<div class="form-group">
<h3>Task In Progress</h3>
<div>
<label>Yes:</label>
<input type="radio"
ng-checked="tr.taskInProgress"
ng-click="tr.taskInProgress = true"
ng-disabled="tr.modalIsOpen">
</div>
<label>No:</label>
<input type="radio"
ng-checked="!tr.taskInProgress"
ng-click="tr.taskInProgress = false"
ng-disabled="tr.modalIsOpen">
</div>
<div class="form-group">
<label>Open the modal:</label>
<button type="button"
class="btn btn-success"
ng-click="tr.beginTask();"
ng-disabled="tr.taskButtonLocked">
<span>Begin Task</span>
</button>
</div>
</form>
</div>
</div>
</div>
<!-- ==== MODAL HTML TEMPLATE ==== -->
<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">
<form>
<div class="form-group">
<label>Task State:</label>
<div style="padding:1em;background:rgba(200, 214, 229,0.3);">
<p>
<span ng-show="!mc.inProgress">
<span>Task is not in progress... </span>
<i class="fa fa-check-square" aria-hidden="true"></i>
</span>
<span ng-show="mc.inProgress">
<span>Task is in progress... </span>
<i class="fa fa-spinner fa-spin" aria-hidden="true"></i>
</span>
</p>
</div>
</div>
<div class="form-group" style="padding-top:1em;">
<h3>Task In Progress</h3>
<div>
<label>Yes:</label>
<input type="radio"
ng-checked="mc.inProgress"
ng-click="mc.inProgress = true">
</div>
<label>No:</label>
<input type="radio"
ng-checked="!mc.inProgress"
ng-click="mc.inProgress = false">
</div>
</form>
</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>
I am trying that on a button click, a div and and input tag are created and the input tag contain ng-model and the div has binding with that input.
Kindly suggest some solution.
You can create the div and input beforehand and and do not show it by using ng-if="myVar". On click make the ng-if="true".
<button ng-click="myVar = true">
In controller : $scope.myVar = false;
$scope.addInputBox = function(){
//#myForm id of your form or container boxenter code here
$('#myForm').append('<div><input type="text" name="myfieldname" value="myvalue" ng-model="model-name" /></div>');
}
Here is another solution, in which there's no need to create a div and an input explicitly. Loop through an array of elements with ng-repeat. The advantage is that you will have all the values of the inputs in that array.
angular.module('app', [])
.controller('AppController', AppController);
AppController.$inject = ['$scope'];
function AppController($scope) {
$scope.values = [];
$scope.add = function() {
$scope.values.push('');
};
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app" ng-controller="AppController">
<button ng-click="add()">Click</button>
<div ng-repeat="value in values track by $index">
<input type="text" ng-model="values[$index]"/>
<div>{{values[$index]}}</div>
</div>
<pre>{{values}}</pre>
</div>
UPDATE. And if you want only one input, it's even simpler, using ng-show.
angular.module('app', []);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<button ng-click="show = true">Click</button>
<div ng-show="show">
<input type="text" ng-model="value"/>
<div>{{value}}</div>
</div>
</div>
You should use $compile service to link scope and your template together:
angular.module('myApp', [])
.controller('MyCtrl', ['$scope', '$compile', '$document' , function MyCtrl($scope, $compile, $document) {
var ctrl = this;
var inputTemplate = '<div><span ng-bind="$ctrl.testModel"></span>--<span>{{$ctrl.testModel}}</span><input type="text" name="testModel"/></div>';
ctrl.addControllDynamically = addControllDynamically;
var id = 0;
function addControllDynamically() {
var name = "testModel_" + id;
var cloned = angular.element(inputTemplate.replace(/testModel/g, name)).clone();
cloned.find('input').attr("ng-model", "$ctrl." + name); //add ng-model attribute
$document.find('[ng-app]').append($compile(cloned)($scope)); //compile and append
id++;
}
return ctrl;
}]);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//code.angularjs.org/1.6.2/angular.js"></script>
<div ng-app="myApp">
<div ng-controller="MyCtrl as $ctrl">
<input type="button" value="Add control dynamically" ng-click="$ctrl.addControllDynamically()"/>
</div>
</div>
UPDATE: to add a new compiled template each time the button is clicked, we need to make a clone of the element.
UPDATE 2: The example above represents a dirty-way of manipulating the DOM from controller, which should be avoided. A better (angular-)way to solve the problem - is to create a directive with custom template and use it together with ng-repeat like this:
angular.module('myApp', [])
.controller('MyCtrl', ['$scope', function MyCtrl($scope) {
var ctrl = this;
ctrl.controls = [];
ctrl.addControllDynamically = addControllDynamically;
ctrl.removeControl = removeControl;
function addControllDynamically() {
//adding control to controls array
ctrl.controls.push({ type: 'text' });
}
function removeControl(i) {
//removing controls from array
ctrl.controls.splice(i, 1);
}
return ctrl;
}])
.directive('controlTemplate', [function () {
var controlTemplate = {
restrict: 'E',
scope: {
type: '<',
ngModel: '='
},
template: "<div>" +
"<div><span ng-bind='ngModel'></span><input type='type' ng-model='ngModel'/></div>" +
"</div>"
}
return controlTemplate;
}]);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="//code.angularjs.org/1.6.2/angular.js"></script>
<div ng-app="myApp">
<div ng-controller="MyCtrl as $ctrl">
<input type="button" value="Add control dynamically" ng-click="$ctrl.addControllDynamically()"/>
<div ng-repeat="control in $ctrl.controls">
<control-template type="control.type" ng-model="control.value"></control-template>
</div>
</div>
</div>
In my angular application, I came into a filter related issue. I have reproduced this issue with a simple live demo as bellow:
https://jsfiddle.net/baoqger/fpo3j6gx/2/
<div ng-app="app">
<div ng-controller="filterCtrl as f">
<input type="text" ng-model="f.inputdata"></input>
<span ng-click="f.setFilter('lowercase')">First Filter</span>
<span ng-click="f.setFilter('uppercase')">Second Filter</span>
<div ng-bind="f.inputdata | f.filtername"></div>
</div>
click First Filter or Second Filter will trigger the setFilter function.
function filterCtrl() {
this.setFilter = function ( name ){
this.filtername = name;
}.bind(this);
}
angular
.module('app', [])
.controller('filterCtrl', filterCtrl)
In the controller, the filtername will be set to lowercase or upper case, depends on which button was clicked as mentioned above.
Then set the filtername as filter method as below:
<div ng-bind="f.inputdata | f.filtername"></div>
But based on the error message, it seems that angular system can't support such usage. Any help?
Try this solution:
Javascript:
.controller('filterCtrl', ['$filter' function($filter){
var self = this;
self.setFilter = function(name){
self.filter = $filter(name);
}
}]);
HTML:
<div ng-app="app">
<div ng-controller="filterCtrl as f">
<input type="text" ng-model="f.inputdata"></input>
<span ng-click="f.setFilter('lowercase')">First Filter</span>
<span ng-click="f.setFilter('uppercase')">Second Filter</span>
<div ng-bind="f.filter?f.filter(f.inputdata):f.inputdata"></div>
</div>
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>
I've got this code:
<html>
<head>
</head>
<div ng-app="" ng-controller="Test">
<input type="text" ng-model="inputty">
<p>{{output}}</p>
</div>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.15/angular.min.js"></script>
<script>
function Test($scope){
if($scope.inputty=="Hello") {
$scope.output="OK!";
} else {
$scope.output="NOT OK!";
}
}
</script>
</html>
But it's not working, the NOT OK! displays. But it's like the if statement can't read from inputty. So it should state OK! when I type Hello in the input box.
You need to add in a watch in your controlller in order to check the value of inputty and inside the watch function have the if loop so that you can change the output scope variable
Code:
function Test($scope) {
$scope.inputty = '';
$scope.$watch('inputty', function () {
if ($scope.inputty == "Hello") {
$scope.output = "OK!";
} else {
$scope.output = "NOT OK!";
}
});
}
Working Fiddle - $watch
Reference for $watch
Alternatively,
You can do it alone in HTML markup using ng-switch
HTML markup
<div ng-app ng-controller="Test">
<input type="text" ng-model="inputty" />
<div ng-switch="inputty">
<p ng-switch-when="Hello">OK!</p>
<p ng-switch-default>NOT OK!</p>
</div>
</div>
Working Fiddle - ng-switch
Reference for ng-switch
If you only change your inputty through textbox, the easiest way is to use ngChange.