Angular: a part of view does not update - angularjs

I have a directive template with the following code
<div class="colorpicker">
<div>Chosen color</div>
<div class="color_swatch" style="background-color: {{ngModel}}"> </div>
<div class="clearfix"></div>
<div>Standard colors</div>
<div class="color_squares">
<div ng-repeat="color in colorList">{{color.trim() == ngModel.trim()}} //does not update
<div class="color_swatch" style="background-color: {{ color }};"></div>
</div>
</div>
<div class="clearfix"></div>
In the directive, I update the ngmodel using the below code to the color that was clicked - the div next to "chosen color" is updated with the selected color.
But, the expression "{{color.trim() == ngModel.trim()}}" always amounts to false.
{{color.trim() == ngModel.trim()}}
I have debugged the code and the values are exactly the same.
What I am missing?

This is probably because your variable is precisely named 'ngModel' see that article for more explanation : http://zcourts.com/2013/05/31/angularjs-if-you-dont-have-a-dot-youre-doing-it-wrong/
To resume this article : never use raw fields use always a dot. So in your scope change
$scope.ngModel
By
$scope.data.ngModel
And in your html change ngModel by data.ngModel.
When using dot you may have some undefined error, this is because you have to initialize the object :
$scope.data={};
Of course you can jsut rename your variable, but you may still have a problem with others directives.

I solved this by removing curly braces around color and using ng-style
<div class="color_swatch" id="colorpicker_selected_color" ng-style="{'background-color': selectedColor}" > </div>

Related

How to get the selecteditem for each row based on its index? [duplicate]

I'm trying to deal with the issue of scope inside of an ng-repeat loop - I've browsed quite a few questions but have not quite been able to get my code to work.
Controller code:
function Ctrl($scope) {
$scope.lines = [{text: 'res1'}, {text:'res2'}];
}
View:
<div ng-app>
<div ng-controller="Ctrl">
<div ng-repeat="line in lines">
<div class="preview">{{text}}{{$index}}</div>
</div>
<div ng-repeat="line in lines">
<-- typing here should auto update it's preview above -->
<input value="{{line.text}}" ng-model="text{{$index}}"/>
<!-- many other fields here that will also affect the preview -->
</div>
</div>
</div>
Here's a fiddle: http://jsfiddle.net/cyberwombat/zqTah/
Basically I have an object (it's a flyer generator) which contains multiple lines of text. Each line of text can be tweaked by the user (text, font, size, color, etc) and I want to create a preview for it. The example above only shows the input field to enter text and I would like that to automatically/as-you-type update the preview div but there will be many more controls.
I am also not sure I got the code right for the looping index - is that the best way to create a ng-model name inside the loop?
For each iteration of the ng-repeat loop, line is a reference to an object in your array. Therefore, to preview the value, use {{line.text}}.
Similarly, to databind to the text, databind to the same: ng-model="line.text". You don't need to use value when using ng-model (actually you shouldn't).
Fiddle.
For a more in-depth look at scopes and ng-repeat, see What are the nuances of scope prototypal / prototypical inheritance in AngularJS?, section ng-repeat.
<h4>Order List</h4>
<ul>
<li ng-repeat="val in filter_option.order">
<span>
<input title="{{filter_option.order_name[$index]}}" type="radio" ng-model="filter_param.order_option" ng-value="'{{val}}'" />
{{filter_option.order_name[$index]}}
</span>
<select title="" ng-model="filter_param[val]">
<option value="asc">Asc</option>
<option value="desc">Desc</option>
</select>
</li>
</ul>

cannot get angular-marked to work against $scope variable

I have a controller that basically assigns text to a $scope variable like this;
$scope['Model'] = ["markdown text 1", "markdown text 2"];
And then I try to use marked on it within a view, like this;
<div ng-repeat="n in Model">
<div marked="n"></div>
</div>
or
<div marked>
<div ng-repeat="n in Model">
{{n}}
</div>
</div>
I just get {{n}} as the output, verbatim. Marked never runs, never does anything to it. I'm completely baffled. I know the text is fine.
I have tried all of the examples and nothing seems to work. It does work if I put in static, hard-coded text between <marked> directives - but nothing dynamic.
The only way I've been able to make anything work is to forcefully use the marked(n) function within the controller - which is far less than ideal and certainly not what I'm wanting to do.
After a lot of trying, I think that the way angular-ui-router is involved may play a part. Here is the HTML structure;
index.html
<div class="content-body">
<ui-view />
</div>
content.html
<ui-view />
entry.html
<div ng-repeat="m in model">
<div marked="m"></div>
</div>
I think I've got it.
<div ng-repeat="m in model">
<div marked="m"></div>
</div>
Works as per this fiddle: https://jsfiddle.net/jorgthuijls/q244srfh/
See, ng-repeat creates its own scope. So, you can bind the m variable to the marked directive.
I got it to work with angular-ui-router too: https://jsfiddle.net/jorgthuijls/ck8by0ze/

ng-click not working on inner div

I have a very simple thing I am trying to do. The ng-click is not working. Any ideas why? Is there a problem with divs that are embedded in another div or am I just too sleepy? That item affected is not included in the code below, but no event is ever registered with the click.
<div ng-switch-when="3" ng-mouseenter="showIcons=true" ng-mouseleave="showIcons=false">
<div ng-if="editPerm" ng-show="showIcons" class="icon_holder" style="width: {{obj.mainwidth}}px;">
<div class="deletebutton"></div>
<div ng-click="equationShow=!equationShow" class="equationspecs"></div>
</div>
<div class="equationBlock">
<div class="eqshow" id="{{obj.itemid}}" ng-show="!obj.showEdit" ng-dblclick="obj.showEdit=!obj.showEdit">
<span mathjax-bind="obj.data.Format_left"></span>=
<span mathjax-bind="obj.data.Format_showequation"></span>=
<span mathjax-bind="obj.data.Format_showsolution"></span>
</div>
If you were able to click on a div with no content in it (sometimes a hard thing to do!), it would simply invert the value of equationShow on the scope.
But that would produce no visible difference. From what I can see in your example, the value of equationShow isn't being used in any way.
Based on your comment, you've probably got a problem with variable scoping.
If, for instance, you did something like this, it'd be more likely to work:
<div ng-init="myVariable = false">
<div ng-if="!myVariable">
<div ng-click="$parent.myVariable = !$parent.myVariable">Show the other div</div>
</div>
<div ng-if="myVariable">
Showing this div
</div>
</div>

angular - failing to bind element's ng-show inside ng-repeat

There is a panel for each contact. I want to show the remove button on a specific panel only when the user mouse over that same panel.
...
<div class="col-sm-3" ng-repeat="contact1 in Contacts">
<div class="panel panel-success" ng-mouseenter="{{contact1.id}}=true" ng-mouseleave="{{contact1.id}}=false)">
<div class="panel-heading">
REMOVE BUTTON
</div>
...
I cant get the reason why this code doesnt work.
There is 2 things in your code that can create problem. First of all, ng-show / ng-mouseneter / ng-mouseleave need an expression. So you don't need to put the {{ }}.
But it wasn't the only one problem. The fact is you were using your id to manage the show property of your item. But this expression need a boolean and you can't just erase your id with a boolean like in ng-mouseneter. To do so, you have to use an other attribute in your item, isShow for example. This will keep your id safe and you will be able to manage your view with it.
So, it give something like this :
<div class="col-sm-3" ng-repeat="contact1 in Contacts">
<div class="panel panel-success" ng-mouseenter="contact1.isShow = true" ng-mouseleave="contact1.isShow = false">
<div class="panel-heading">
REMOVE BUTTON
</div>
....
Would be nice to see a working example, but for the start the angular directives you've used require an expressions, so try removing the {{}} from ng-mouseenter, ng-mouseleave and ng-show.
So, it should be like ng-show="contact1.id".
Try applying this. Hope it works for you.
Remove the brackets from your assignment statements.
The brackets are to render a variable. Since you're assigning, instead of ng-mouseenter="{{contact1.id}}=true" you'll want to do ng-mouseenter="contact1.id=true"
You're previous code was the equivalent of writing something like null=true, or whatever value was already assigned to contact.id. The new code assigns contact.id to the value you specified.
EDIT: You can just use a local variable.
<div class="col-sm-3" ng-repeat="contact1 in Contacts">
<div class="panel panel-success" ng-mouseenter="showButton=true" ng-mouseleave="showButton=false">
<div class="panel-heading">
REMOVE BUTTON
</div>
</div>
</div>

Angular.js ng-switch-when not working with dynamic data?

I'm trying to get Angular to generate a CSS slider based on my data. I know that the data is there and am able to generate it for the buttons, but the code won't populate the ng-switch-when for some reason. When I inspect the code, I see this twice (which I know to be correct as I only have two items):
<div ng-repeat="assignment in assignments" ng-animate="'animate'" class="ng-scope">
<!-- ngSwitchWhen: {{assignment.id}} -->
</div>
My actual code:
<div ng-init="thisAssignment='one'">
<div class="btn-group assignments" style="display: block; text-align: center; margin-bottom: 10px">
<span ng-repeat="assignment in assignments">
<button ng-click="thisAssignment = '{{assignment.id}}'" class="btn btn-primary">{{assignment.num}}</button>
</span>
</div>
<div class="well" style="height: 170px;">
<div ng-switch="thisAssignment">
<div class="assignments">
<div ng-repeat="assignment in assignments" ng-animate="'animate'">
<div ng-switch-when='{{assignment.id}}' class="my-switch-animation">
<h2>{{assignment.name}}</h2>
<p>{{assignment.text}}</p>
</div>
</div>
</div>
</div>
</div>
EDIT: This is what I'm trying to emulate, though with dynamic data. http://plnkr.co/edit/WUCyCN68tDR1YzNnCWyS?p=preview
From the docs —
Be aware that the attribute values to match against cannot be expressions. They are
interpreted as literal string values to match against. For example, ng-switch-when="someVal"
will match against the string "someVal" not against the value of the expression
$scope.someVal.
So in other words, ng-switch is for hardcoding conditions in your templates.
You would use it like so:
<div class="assignments">
<div ng-repeat="assignment in assignments" ng-animate="'animate'">
<div ng-switch="assignment.id">
<div ng-switch-when='1' class="my-switch-animation">
<h2>{{assignment.name}}</h2>
<p>{{assignment.text}}</p>
</div>
</div>
</div>
Now this might not fit your use case exactly, so it's possible you'll have to rethink your strategy.
Ng-If is probably what you need — also, you need to be aware of "isolated" scopes. Basically when you use certain directives, like ng-repeat, you create new scopes which are isolated from their parents. So if you change thisAssignmentinside a repeater, you're actually changing the variable inside that specific repeat block and not the whole controller.
Here's a demo of what you're going for.
Notice I assign the selected property to the things array (it's just an object).
Update 12/12/14: Adding a new block of code to clarify the use of ng-switch. The code example above should be considered what not to do.
As I mentioned in my comment. Switch should be thought about exactly like a JavaScript switch. It's for hardcoded switching logic. So for instance in my example posts, there are only going to be a few types of posts. You should know a head of time the types of values you are going to be switching on.
<div ng-repeat="post in posts">
<div ng-switch on="post.type">
<!-- post.type === 'image' -->
<div ng-switch-when="image" class="post post-image">
<img ng-src="{{ post.image }} />
<div ng-bind="post.content"></div>
</div>
<!-- post.type === 'video' -->
<div ng-switch-when="video" class="post post-video">
<video ng-src="{{ post.video }} />
<div ng-bind="post.content"></div>
</div>
<!-- when above doesn't match -->
<div ng-switch-default class="post">
<div ng-bind="post.content"></div>
</div>
</div>
</div>
You could implement this same functionality with ng-if, it's your job to decide what makes sense within your application. In this case the latter is much more succinct, but also more complicated, and you could see it getting much more hairy if the template were any more complex. Basic distinction is ng-switch is declarative, ng-if is imperative.
<div ng-repeat="post in posts">
<div class="post" ng-class="{
'post-image': post.type === 'image',
'post-video': post.type === 'video'">
<video ng-if="post.type === 'video'" ng-src="post.video" />
<img ng-if="post.type === 'image'" ng-src="post.image" />
<div ng-bind="post.content" />
</div>
</div>
Jon is definitely right on. Angular does not support dynamic ngSwitchWhen values. But I wanted it to. I found it actually exceptionally simple to use my own directive in place of ngSwitchWhen. Not only does it support dynamic values but it supports multiple values for each statement (similar to JS switch fall-throughs).
One caveat, it only evaluates the expression once upon compile time, so you must return the correct value immediately. For my purposes this was fine as I was wanting to use constants defined elsewhere in the application. It could probably be modified to dynamically re-evaluate the expressions but that would require more testing with ngSwitch.
I am use angular 1.3.15 but I ran a quick test with angular 1.4.7 and it worked fine there as well.
Plunker Demo
The Code
module.directive('jjSwitchWhen', function() {
// Exact same definition as ngSwitchWhen except for the link fn
return {
// Same as ngSwitchWhen
priority: 1200,
transclude: 'element',
require: '^ngSwitch',
link: function(scope, element, attrs, ctrl, $transclude) {
var caseStms = scope.$eval(attrs.jjSwitchWhen);
caseStms = angular.isArray(caseStms) ? caseStms : [caseStms];
angular.forEach(caseStms, function(caseStm) {
caseStm = '!' + caseStm;
ctrl.cases[caseStm] = ctrl.cases[caseStm] || [];
ctrl.cases[caseStm].push({ transclude: $transclude, element: element });
});
}
};
});
Usage
Controller
$scope.types = {
audio: '.mp3',
video: ['.mp4', '.gif'],
image: ['.jpg', '.png', '.gif'] // Can have multiple matching cases (.gif)
};
Template
<div ng-switch="mediaType">
<div jj-switch-when="types.audio">Audio</div>
<div jj-switch-when="types.video">Video</div>
<div jj-switch-when="types.image">Image</div>
<!-- Even works with ngSwitchWhen -->
<div ng-switch-when=".docx">Document</div>
<div ng-switch-default>Invalid Type</div>
<div>

Resources