conditionally call a function in angular from html - angularjs

In my chat application I want to call a audio play function from html, which will play only when user received msg from another users.
<div ng-bind-html="m.msg">
</div>
So, what I'm trying is whenever value came from this 'm.msg', I want call a function which will play sound in background.

All you need to do is use angularjs watch.
angular.module('app', [])
.controller('parentCtrl', function($scope) {
$scope.m = {
msg: ""
};
// Watch the msg.
$scope.$watch("m.msg", function(newVal, oldVal) {
//In case it change call playAudio function
if (newVal !== oldVal) {
playAudio();
}
});
function playAudio(){
alert("Set Code for Play Audio here");
}
});
.msg-wim{
background-color:white;
width:100%;
height:100px;
border:1px solid;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="parentCtrl">
<input type="text" ng-model="m.msg" placeholder="Type Text...">
<hr>
<h1>For each char u type in the textbox alert will display</h1>
<div class="msg-wim" ng-bind="m.msg">
</div>
</div>
</div>

Related

Angularjs autocomplete ng-click does not work

I'm trying to write autocomplete in Angularjs. It works for me except the click on the suggestion. From the console log it looks like whenever I click on the suggestion, ng-blur of the input element is called as it input element loses focus and ng-click is never called. Can anybody suggest a solution here?
Here is my code.
<!DOCTYPE html>
<head>
<title>Autocomplete</title>
<style>.wrapper {display: none;}.wrapper ul {list-style-type: none;}.wrapper li {padding: 5px;line-height: 25px;cursor: pointer;}</style>
<!-- Angular JS -->
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.7.5/angular.min.js"></script>
</head>
<body ng-app="MyApp">
<div ng-controller="SuggestionCtrl">
<form action="/index.html">
<input type="search" name="q" autocomplete="off"
ng-model="q"
ng-focus="showSuggesions()"
ng-blur="hideSuggesions()"
ng-change="getSuggestion()">
<div class="wrapper"
ng-if="hasSuggestions"
ng-style="suggestionStyle">
<ul>
<li ng-repeat="suggestion in suggestions"
ng-click="search(suggestion)">
{{suggestion}}
</li>
</ul>
</div>
</form>
</div>
var app = angular.module("MyApp", []);
app.controller("SuggestionCtrl", function ($scope) {
$scope.suggestions = ["India", "United States", "England", "Australia"];
$scope.showSuggesions = function () {
$scope.suggestionStyle = { display: "block", 'background-color': '#ddd' };
};
$scope.hideSuggesions = function () {
$scope.suggestionsVisible = false;
$scope.suggestionStyle = { display: "none" };
console.log('hideSuggestions called');
};
$scope.hasSuggestions = function(){
return $scope.suggestions.length > 0;
}
$scope.getSuggestion = function () {
// get suggestions from api
};
$scope.search = function (suggestion) {
window.location = window.location + "?q=" + suggestion;
};
});
The click event executes after blur - list with suggestions hides before you are able to click it. The simple solution is to use mousedown instead of click
<input type="search" name="q" autocomplete="off"
ng-model="q"
ng-focus="show=true"
ng-blur="show=false">
<div class="wrapper"
ng-style="suggestionStyle">
<ul ng-show="show">
<li ng-repeat="suggestion in suggestions">
<a ng-mousedown="search(suggestion)">{{suggestion}}</a>
</li>
</ul>
plunker: http://plnkr.co/edit/Y4e4dYD4qJZwnNRmgWiN?p=preview

Ng-style function called more than once

In this plunk I have a div with a border width that is determined by the value in an input field. I achieve that with ng-style containing a getBorder() function.
My issue is that getBorder() is called twice and sometimes three times, instead of once. Why does this happen and how to fix it?
HTML
Width: <input type="number" ng-model="borderWidth"/>
<br/>
<div style="background-color:orange;height:200px;width:100px"
ng-style="{ 'border': getBorder() }"></div>
JavaScript
var app = angular.module('app', []);
app.controller('ctl', function ($scope) {
$scope.getBorder = function(){
alert('getBorder called');
return $scope.borderWidth + 'px solid black';
};
});
This is because of the digest cycles in AngularJS.
AngularJS registers watchers to observe changes in the scope, and as soon as a change happens, it refreshes the bindings between corresponding views/models using digest cycles. This is the reason why you can see live changes in the data and on the screen.
ngModel is one of the directives which registers a watcher. So, the problem you came across, is not really a problem, because ng-style is trying to get the value using getBorder().
I hope that this solution solved your problem
var app = angular.module('app', []);
app.controller('ctl', function ($scope) {
$scope.borderWidth = 1;
$scope.$watch('borderWidth', function (newVal, oldVal) {
console.log()
if (angular.isDefined(newVal)) {
$scope.styleBorder = newVal + 'px solid black';
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<html ng-app="app">
<body>
<div ng-controller="ctl">
Width: <input type="number" ng-model="borderWidth"/>
<br/>
<div
style="background-color:orange;height:200px;width:100px;"
ng-style='{"border": styleBorder}'
></div>
</div>
</body>
</html>

How to replace text on field after click Angular?

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

How to bind an alert message with the controller?

Hi guys I've been experimenting with a simple commenting app with AngularJS and I'm stuck on how to get an alert message popup in the view if a user inputs an empty string into an input field.
The HTML view and ng-show logic as below:
<div ng-show="alert===true" class="alert alert-warning alert-dismissible inner" role="alert">
<button type="button" class="close" data-dismiss="alert"><span aria-hidden="true">×
</span><span class="sr-only">Close</span></button>
<strong>Warning!</strong> You did not submit a comment.
</div>
The controller view and $scope logic as below:
// pushes data back to Firebase Array
$scope.addComment = function(){
if ($scope.newComment.text === ''){
$scope.alert = true;
}
else {
$scope.alert = false;
}
$scope.comments.$add($scope.newComment);
$scope.newComment = {text: '', date: ''};
};
The problem is that although I can bind the alert message logic to the HTML view, the alert message only shows up once and cannot be re-used again if the user types in an empty string again.
Should I use a while loop or something for this? Any help would be much appreciated!
EDIT:
Thanks to meriadec's feedback, I have made a fix using a more simple codebase, as follows.
The HTML view and ng-show logic as below:
<div ng-show="alert===true" class="alert alert-warning inner" role="alert">
<button type="button" class="btn" ng-click="alert=false"><span aria-hidden="true">×
</span><span class="sr-only">Close</span></button>
<strong>Warning!</strong> You did not submit a comment.
</div>
The controller view and $scope logic as below:
// pushes data back to Firebase Array
$scope.addComment = function(){
if ($scope.newComment.text === ''){
return $scope.alert = true;
};
$scope.comments.$add($scope.newComment);
$scope.newComment = {text: '', date: ''};
};
You can re-set your alert property to false when clicking the close button. BUT, as you got an ngShow directive, your alert is in a child scope so you need to use an object for having a correct data binding between scopes. More info here.
See this :
angular.module('demo', []);
angular.module('demo')
.controller('DemoCtrl', function ($scope) {
$scope.ui = { alert: false };
$scope.addComment = function () {
if (!$scope.myComment) {
$scope.ui.alert = true;
} else {
alert('well !');
}
}
});
.alert {
position: absolute;
top: 15px;
left: 20%;
right: 20%;
width: 300px;
background: white;
border: 1px solid black;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="demo" ng-controller="DemoCtrl">
<div class="alert" ng-show="ui.alert">
<button ng-click="ui.alert = false">close</button>
You did not enter any comment
</div>
<form ng-submit="addComment()">
<input type="text" ng-model="myComment">
<input type="submit">
</form>
</div>

How to show message for a certain time in angularjs

I'm displaying a message when the user clicks on the button.
I want to show this message for 10 seconds and then hide it.
My code is the following:
<script>
function Ctrl($scope, $window) {
$scope.greeting = 'Hello, World!';
$scope.doGreeting = function() {
$scope.msg="hi";
};
}
</script>
<div ng-controller="Ctrl">
<input type="text" ng-model="greeting" />
<button ng-click="doGreeting()">click</button>
{{msg}}
</div>
You can set a variable that determines whether to show the message or not and hide it and after 10,000 seconds. You will have to inject $timeout as shown below. Then in your view you will need to wrap {{msg}} in a span in order to use ng-show
<script>
function Ctrl($scope, $window, $timeout) {
$scope.greeting = 'Hello, World!';
$scope.showGreeting = false;
$scope.doGreeting = function() {
$scope.msg="hi";
$scope.showGreeting = true;
$timeout(function(){
$scope.showGreeting = false;
}, 10000);
};
}
</script>
<div ng-controller="Ctrl">
<input type="text" ng-model="greeting" />
<button ng-click="doGreeting()">click</button>
<span ng-show="showGreeting ">{{msg}}</span>
</div>
The way I did to show a message for a certain time in angularjs was using AngularJS-Toaster library
To use the library follow this steps:
<link href="https://cdnjs.cloudflare.com/ajax/libs/angularjs-toaster/0.4.9/toaster.min.css" rel="stylesheet" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.0/angular.min.js" ></script>
<script src="https://code.angularjs.org/1.2.0/angular-animate.min.js" ></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angularjs-toaster/0.4.9/toaster.min.js"></script>
Add toaster container directive:
<toaster-container></toaster-container>
Prepare the call of toaster method:
// Display an info toast with no title
angular.module('main', ['toaster'])
.controller('myController', function($scope, toaster) {
$scope.pop = function(){
toaster.pop('success', "title", "text");
};
});
Call controller method on button click:
<div ng-controller="myController">
<button ng-click="pop()">Show a Toaster</button>
</div>
Here you can see a Plunker showing many kinds of toasts showing differents messages
Add the $timeout dependency to your controller. Here's a fiddle:
<div ng-app>
<div ng-controller="Ctrl">
<input type="text" ng-model="greeting" />
<button ng-click="doGreeting()">click</button>
<div class="ng-hide" ng-show="showMessage">{{msg}} {{ greeting }}</div>
</div>
</div>
function Ctrl($scope, $window, $timeout) {
var messageTimer = false,
displayDuration = 5000; // milliseconds (5000 ==> 5 seconds)
$scope.showMessage = false;
$scope.msg = "hi";
$scope.doGreeting = function () {
if (messageTimer) {
$timeout.cancel(messageTimer);
}
$scope.showMessage = true;
messageTimer = $timeout(function () {
$scope.showMessage = false;
}, displayDuration);
};
}

Resources