Use angular conditional to display message based on array selection - angularjs

I'm having trouble getting the messages from the messages array to display based on the user selected. I'm currently able to show all of the messages on the left side, but it needs to only show the selected message on the left, based on the user associated with it on the right. The message showing below each name, needs to be the message showing on the left when clicking the username.
the controller and directives
var movieApp = angular.module("movieApp",[]);
movieApp.controller("movieController",function($scope){
$scope.messages = [{
user:"aleksandra",
message:"this is aleksandras message"
},
{
user:"evan",
message:"this is evan message"
},
{
user:"tom",
message:"this is toms message"
},
{
user:"jarid",
message:"this is jarids message"
}];
$scope.response = [];
$scope.sendMessage = function(response){
$scope.toggle = $scope.toggle;
$scope.response.push(response);
console.log(response);
};
});
movieApp.directive("usersList", function(){
return {
restrict: "E",
scope: false,
template: "<p>Users</p>"+
"<ol class='list-unstyled animated fadeInDown'>"+
"<li ng-repeat='message in messages'>"+
"<h5 ng-click='showDetails = ! showDetails'>{{message.user}}</h5>"+
"<div ng-show='showDetails'>"+
"<p>{{message.message}}</p>"+
"</div>"+
"</li>"+
"</ol>"
};
});
movieApp.directive("messagesList", function(){
return {
restrict: "E",
scope: false,
template: "<div class='panel panel-primary'>"+
"<div class='panel-heading'>"+
"<span class='glyphicon glyphicon-comment'></span> Chat</div>"+
"<div class='panel-body body-panel'>"+
"<ol class='list-unstyled'>"+
"ONLY SHOW THE MESSAGE FOR THE USER SELECTED ON THE RIGHT"+
"<li ng-repeat='message in messages'>"+
"<p>{{message.message}}</p>"+
"</li>"+
"</ol>"+
"</div>"+
"<div class='panel-footer clearfix'>"+
"<form name='form'>"+
"<input type='text' name='message' ng-model='response' class='form-control' />"+
"<span class='col-lg-6 col-lg-offset-3 col-md-6 col-md-offset-3 col-xs-12' style='margin-top: 10px'>"+
"<button class='btn btn-warning btn-lg btn-block' id='btn-chat' ng-click='sendMessage(messages)' ng-disabled='!form.message.$dirty'>Send</button>"+
"</span>"+
"</form>"+
"</div>"+
"</div>"
};
});
markup
<div ng-controller="chatController">
<div class="container">
<div class="row">
<div class="col-xs-9">
<messages-list></messages-list>
</div>
<div class="col-xs-3">
<users-list></users-list>
</div>
</div>
</div>
</div>
Current Plunker: Link

To achieve the solution you needed, call a method on usersList directive when clicked on userName and toggle the message
I have taken a toggleDetails() method on the directive.
<h5 ng-click='toggleDetails(message)'>{{message.user}}</h5>
Here is a code snippet for the same
chatApp.directive("usersList", function(){
return {
restrict: "E",
scope: false,
template: "<p>Users</p>"+
"<ol class='list-unstyled animated fadeInDown'>"+
"<li ng-repeat='message in messages'>"+
"<h5 ng-click='toggleDetails(message)'>{{message.user}}</h5>"+
"<div ng-show='message.showDetails'>"+
"<p>{{message.message}}</p>"+
"</div>"+
"</li>"+
"</ol>"
,
link: function(scope) {
scope.toggleDetails = function(message)
{
angular.forEach(scope.messages, function(value, key){
if(message != value)
value.showDetails = false;
});
message.showDetails = !message.showDetails;
}
}
}
});
Here is a Working DEMO

Here's an alternate that uses the $index of the ng-repeat so there isn't a need for the extra property on each message. Instead the controller $scope has a shownMessage property.
ng-repeat='message in messages' ng-if='shownMessage === $index'

var selectedUser;//get when user clicked
var selectedUserMessages=angular.filter('filter')($scope.messages,
{user:selectedUser});
you can now bind the found items where you want

Related

How to toggle edit and save using directive in angular js

I want to edit and save content in selected directive.The directive is populated by ng-repeat. On button click visible items should change to input field and again on click it should reverse
Directive is
.directive('component', function() {
var link = function(scope, element, attrs) {
var render = function() {
var t = scope.layouts[scope.type][attrs.indexs];
var icon = scope.layouts[scope.type][attrs.indexs];
var v = attrs.value;
if(scope.type=="edit"){
element.html('<input type="' + t + '" ng-model="vm.name" value="'+v+'">');
if(attrs.indexs==1){
element.html('<' + t + '>Save');
}}
if(scope.type=="display"){
element.html('<' + t + ' ng-model="'+v+'" >'+v+'</'+t+'>');
if(attrs.indexs==1){
element.html('<' + t + ' >Edit');
}}};
scope.$watch('type', function(newValue, oldValue) {
render();
});
};
return {
restrict : 'E',
link : link
}
});
plunker Link
Problem is on click all directive is changed to editable and vice-versa.
How can I make it work on selected set of directive
Try something like the following. It's much simpler to use a template with a directive than trying to modify the html directly.
Directive
angular.module('myApp', [])
.controller('MyController', MyController)
.directive('component', function(){
return {
template: [
'<div>',
'<span style="font-weight:bold" ng-show="!editing">{{ value }} <button ng-click="editing = true">Edit</button></span>',
'<span ng-show="editing"><input type="input" ng-model="value"><button ng-click="editing = false">Save</button></span>',
'</div>'
].join(''),
restrict: 'E',
scope: {
value: '=value'
},
link: function($scope){
$scope.editing = false;
}
}
});
HTML
<div class="col-sm-12" ng-repeat="s in vm.allCat track by $index">
<div class="col-sm-1 text-muted">Name</div>
<div class="col-sm-9 text-left">
<component value="s.name"></component>
</div>
</div>
</div>
I've forked your plunker here.

AngularJS custom directive - map isolate scope to new child scope

I created a custom directive for bootstrap alerts. My alerts display fine (hard code and data bind). Based on the alert type, I want display a unique header into my alert message based on the returned scope values (success, info, warning, danger). Currently I'm passing the type into <h1> but I don't want those values, they need to be custom.
<!-- data binding example -->
<trux-alert ng-repeat="alert in alerts" type="{{alert.type}}" close="closeAlert($index)">{{alert.msg}}</trux-alert>
<!-- hard coded example -->
<trux-alert close="close" type="warning">This is an important warning message!</trux-alert>
Inside my directive, the scope is isolated using scope: '#' (one-way)
.directive('truxAlert', function() {
return {
scope: {
type: '#',
close: '&'
},
replace: true,
transclude: true,
template:
'<div class="alert" '+
'ng-class="[\'alert-\' + (type || \'warning\'), closeable ? \'alert-dismissible\' : null]" '+
'role="alert">'+
'<button ng-show="closeable" '+
'type="button" class="close" '+
'ng-click="close({$event: $event})" '+
'data-dismiss="alert" aria-label="Close">'+
'<span aria-hidden="true">×</span>'+
'<span class="sr-only">Close</span>'+
'</button>'+
'<h1>{{type}}</h1>'+
'<div ng-transclude></div>'+
'</div>',
link: function (scope, element, attrs) {}
}
});
This would be easier if all my values were pulled through data binding, but I need to allow for manual hard coded option. I know with one-way isolated scopes '#' I can't change these values though DOM manipulation. I can't use '=' or '&' for two-way because the values are strings.
How do I solve for this problem?
My recommendation is have one attribute for the control the open/closed state of the directive's alert and another attribute for the dismiss handler function.
angular.module("myApp").directive('truxAlert', function() {
return {
scope: {
type: '#',
dismissHandler: '&',
title: '#',
open: '='
},
replace: true,
transclude: true,
template:
'<div class="alert" ng-show="open" '+
'ng-class="[\'alert-\' + type]" '+
'role="type">'+
'<button type="button" class="close" '+
'ng-click="truxClose($event)" '+
'data-dismiss="alert" aria-label="Close">'+
'<span aria-hidden="true">×</span>'+
'<span class="sr-only">Close</span>'+
'</button>'+
'<h1>{{title+" "+type}}</h1>'+
'<div ng-transclude></div>'+
'</div>',
link: function (scope, element, attrs) {
console.log("truxAlert linking");
if (!scope.type) { scope.type="warning" }
scope.truxClose = function(event) {
console.log("truxClose "+event);
if (attrs.dismissHandler) {
scope.dismissHandler({$event: event});
return;
}
scope.open = false;
};
}
};
});
The linking function of the directive determines if the dismiss-handler attribute exists and either invokes the dismiss handler or directly closes the alert.
The DEMO PLNKR show the directive being used both with an ng-repeat directive and in a standalone manner.
Maybe, i don't understand you question.
You want to do so jsfiddle?
<form name="ExampleForm" id="ExampleForm">
<span simple="{{val}}">{{val}} - value from data-binding </span>
<br>
<span simple="valueTwo">valueTwo - hard code value</span>
</form>
And js controller
.controller('ExampleController', function($scope, $rootScope, $alert) {
$scope.val = "valueOne";})
And js directive
.directive('simple', function() {
return {
restrinct: 'A',
scope: {
simple: "#"
},
link: function(scope) {
console.log(scope.simple, typeof(scope.simple));
}
}})
UPDATED
angular.module('ExampleApp', ['use', 'ngMessages'])
.controller('ExampleOneController', function($scope) {
$scope.val = "valueOne";
$scope.$on('pass.from.directive', function(event, value) {
$scope.valFromDirective = value;
});
})
.controller('ExampleTwoController', function($scope) {
$scope.val = "valueTwo";
$scope.$on('pass.from.directive', function(event, value) {
$scope.valFromDirective = value;
});
})
.controller('ExampleThreeController', function($scope) {
$scope.val = "valueThree";
$scope.$on('pass.from.directive', function(event, value) {
$scope.valFromDirective = value;
});
})
.directive('simple', function($interval) {
return {
restrinct: 'A',
scope: {
simple: "#"
},
link: function(scope) {
var i = 0;
$interval(function() {
i++;
scope.$emit('pass.from.directive', scope.simple + i);
}, 1000);
}
}
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.9/angular-messages.min.js"></script>
<script src="https://cdn.rawgit.com/Stepan-Kasyanenko/use-form-error/master/src/use-form-error.js"></script>
<div ng-app="ExampleApp">
<div ng-controller="ExampleOneController">
<h3>
ExampleOneController
</h3>
<form name="ExampleForm" id="ExampleForm">
<div simple="{{val}}">{{val}} - value from scope </div>
<div>{{valFromDirective}} - value from directive </div>
</form>
</div>
<div ng-controller="ExampleTwoController">
<h3>
ExampleTwoController
</h3>
<form name="ExampleForm" id="ExampleForm">
<div simple="{{val}}">{{val}} - value from scope </div>
<div>{{valFromDirective}} - value from directive </div>
</form>
</div>
<div ng-controller="ExampleThreeController">
<h3>
ExampleThreeController
</h3>
<form name="ExampleForm" id="ExampleForm">
<div simple="{{val}}">{{val}} - value from scope </div>
<div>{{valFromDirective}} - value from directive </div>
</form>
</div>
</div>

How to check conditions in angularjs

I am trying to open up a modal in my application, based on particular click it should open that respective modal.I tried ng-if and ng-switch concept but it didn't worked. So please help me..,
Thanks!
Here is my code..,
<div ng-controller="projectsController">
<ul>
<li>Bangalore</li>
<li>Mangalore</li>
<li>Mysore</li>
</ul>
<div ng-switch on="id">
<div ng-switch-when="A">
<modal-dialog show='modalShown' width='800px' height='50%'>
<p>Modal Content Goes here</p>
</modal-dialog>
</div>
<div ng-switch-when="B">
<modal-dialog show='modalShown' width='800px' height='50%'>
<p>Second Modal Content Goes here</p>
</modal-dialog>
</div>
</div>
</div>
/*app.js file*/
myApp.controller('projectsController', ['$scope', function($scope) {
$scope.modalShown = false;
$scope.toggleModal = function() {
$scope.modalShown = !$scope.modalShown;
};
}]);
//This is my directive in app.js i.e.,both controller and directive are in
app.js file
myApp.directive('modalDialog', function() {
return {
restrict: 'E',
scope: {
show: '='
},
replace: true,
transclude: true,
link: function(scope, element, attrs) {
scope.dialogStyle = {};
if (attrs.width)
scope.dialogStyle.width = attrs.width;
if (attrs.height)
scope.dialogStyle.height = attrs.height;
scope.hideModal = function() {
scope.show = false;
};
},
template: "<div class='ng-modal' ng-show='show'><div class='ng-modal-overlay' ng-click='hideModal()'></div><div class='ng-modal-dialog' ng-style='dialogStyle'><div class='ng-modal-close' ng-click='hideModal()'>X</div><div class='ng-modal-dialog-content' ng-transclude></div></div></div>"
};
});
I'm not sure where the modal-dialog directive is coming from but it's possible the show attribute in it expects an expression. You might want to change it to:
<modal-dialog show="modalShown === true" width="800px" height="50%">

Find clicked div angular directive

I simply want to find the clicked div with using a directive and what I have tried:
.directive('blocks', blocks);
function blocks(){
var linkFunc;
linkFunc = function(scope,element,attrs){
element.bind('click', function(){
//assign clicked div
var selectedDiv = $(this);
if(selectedDiv.hasClass('block1')){
console.log('block1 is clicked!');
}
});
};
return{
restrict: 'E',
link: linkFunc,
template: '<div class="block block1 block_unactive">DIV 1</div>' +
'<div class="block block2 block_unactive">DIV 2</div>' +
'<div class="block block3 block_unactive">DIV 3</div>' +
'<div class="block block4 block_unactive">DIV 4</div>'
};
};
that doesn't work.. How can I assign the clicked div as selectedDiv?
For Exp: On click a div; check the click div and if the clicked div hasClass 'block1' do block1 actions.. if the div hasClass 'block2' do block2 actions... etc..
Thank you in advance!
i've another way to handle issue like that, passing div number to a service which will apply the desired action.
we have three files
the view index.html
<section ng-controller="BlockController as block">
<ul>
<li ng-class="{ selected: block.isSet(1) }">
<a href ng-click="block.setTab(1)">Block 1</a></li>
<li ng-class="{ selected: block.isSet(2) }">
<a href ng-click="block.setTab(2)">Block 2</a></li>
...........
</ul>
</section>
the controller main.js
var app = angular.module('mainApp', ["ServicesModule"]);
app.controller('BolckController',["service",function("service"){
this.block = 1;
this.setBlock = function(newValue){
this.block = newValue;
//service is defined in servicesModule.js
service.doBlockAction(newValue);
};
this.isSet = function(blockName){
return this.block === blockName;
};
}
] );
the service servicesModule.js
var ServiceApp = angular.module('ServicesModule', []);
ServiceApp.factory('service', function() {
var doAction=function(BlockName){
if(BlockName === 1)
{
console.log('block1 is clicked!');
}else{if(BlockName === 2)}
console.log('block2 is clicked!');
};
return {
doBlockAction : function(blockName) {
return doAction(blockName);
}
}
});
I dont test the syntax but the logic make sense to work properly
i hope it helps

How to get the name of model passed into the function in AngularJS?

I have a scenario where i need to know the value and name of model passed in to the function.
I tried the following
$scope.rad='fff';
app.directive('kmRadio', function() {
return{
restrict:'E',
compile: function(element,attrs)
{
var model = {l:''};
model.l = attrs.kmModel;
var str1="n in ";
var str2=attrs.kmOption;
var repeat=str1.concat(str2);
var htmlText='<div><div ng-switch on="format">'+
'<div ng-switch-when="kmForm">'+
'<div>'+
'<div class="floatLeft">'+
''+attrs.title+''+
'</div>'+
'<ul>'+
'<li class="rowlist" ng-repeat="'+repeat+'"> {{n}}<input type="radio" ng-model="'+attrs.kmModel+'" name="a" ng-click="radioValueChanged(n,'+attrs.kmModel+')"/></option>'+
'</ul>'+
'{{'+attrs.kmModel+'}}'+
''+attrs.kmModel+''+
''+model.l+''+
'</div>'+
'</div>'+
'<div ng-switch-when="kmPreview">'+
'<div>'+attrs.title+'<input type="radio" ng-model="'+attrs.kmModel+'" disabled="true"/></div>'+
'</div>'+
'</div></div>';
element.replaceWith(htmlText);
}
}
})
The following code is responsible for calling the function
'<li class="rowlist" ng-repeat="'+repeat+'"> {{n}}<input type="radio" ng-model="'+attrs.kmModel+'" name="a" ng-click="radioValueChanged(n,'+attrs.kmModel+')"/></option>'+
$scope.radioValueChanged = function (value,model) {
//alert("Changed value"+value + model);
alert(value +" and " + model);
//alert("model "+ model );
}
In HTML , i have a code like below
<km-radio km-model="rad" title="Gender" km-option="['De','CM','PM']"></km-radio>
When i tap on radio button in html, i am getting the o/p De and fff, but what i need is o/p De and rad
See the plunker code and check the directive kmRadio
I rewrote your directive to get the binding from the attributes parameter of the link function:
app.directive('kmRadio', function($parse) {
return {
restrict: 'E',
replace: true,
templateUrl: 'kmRadio.html',
scope: true,
link: function(scope, element, attr) {
scope.kmModel = scope.$eval(attr.kmModel);
scope.binding = attr.kmModel;
scope.title = attr.title;
scope.kmOption = scope.$eval(attr.kmOption);
}
}
})
where kmRadio.html is:
<div>
<div ng-switch on="format">
<div ng-switch-when="kmForm">
<div>
<div class="floatLeft">{{title}}</div>
<ul>
<li class="rowlist" ng-repeat="n in kmOption">
{{n}} <input type="radio" ng-model="$parent.kmModel" ng-click="radioValueChanged(n, binding)" ng-value="n"/>
</li>
</ul>
bound to: {{binding}}, value: {{kmModel}}
</div>
</div>
<div ng-switch-when="kmPreview">
<div>{{title}}
<input type="radio" ng-model="kmModel" disabled="true" />
</div>
</div>
</div>
</div>
Here is a working demo: http://plnkr.co/edit/2q8a8B4zNGpQ0C5V1x8D?p=preview

Resources