I have a knockout expression below:
<span class='icon' data-bind='css: step_type() '></span>
if my step_type() return register :
<!-- in case of step_type() return a register -->
<span class='icon 0 1 2 3 4 5 6 7' data-bind='css: step_type() '></span>
<!-- in case of step_type() return a date -->
<span class='icon 0 1 2 3' data-bind='css: step_type() '></span>
What I noticed from the output knockout does not take expression value correctly instead it takes indices of each character in the string value. below is what I expected to see
<!-- in case of step_type() return: date -->
<span class='icon date' data-bind='css: step_type() '></span>
<!-- in case of step_type() return: register -->
<span class='icon register' data-bind='css: step_type() '></span>
Do I miss something ? Please help how to get this done.
From what i understood from your question
You need to add a css to a element conditionally . so, we need to do something like this .
Input :
<span class='icon' data-bind='css:{"abc":true}'></span>
OutPut :
<span class='icon abc' data-bind='css:{"abc":true}'></span>
If you need a if check on top of element here we go
<!-- ko if : step_type()== 'your value' -->
<span class='icon' data-bind='css:{"abc":true}'></span>
<!--/ko-->
Edit :
Then you need to have computed of step_type like below
vm.step_type= ko.Computed(function() {
return (check condition here) ? "register" : "date";
}, vm);
later on in you binding do like
<span class='icon' data-bind='css:step_type'></span> **(i/p)**
<span class='icon register' data-bind='css:step_type'></span> **(o/p)**
You can refer the Docs here neatly mentioned how to deal
Working fiddle here
Related
I am using the contentEditable attribute of Angular 6 for editing the content of the element (in the ngFor)
How I can set focus on a tag element when it's contentEditable attribute is true?
<div class="tag" *ngFor="let tag of tags">
<span [contentEditable]="underUpdateTagId==tag.id" [textContent]="tag.title
(input)="tag.title=$event.target.textContent">
</span>
<span *ngIf="underUpdateTagId!=tag.id" class="edit text-info" (click)="beforeEdit(tag)">
<i class="fas fa-pencil-alt"></i>
</span>
<span *ngIf="underUpdateTagId==tag.id" class="update text-success" (click)="editTag(tag)">
<i class="fas fa-check save"></i>
</span>
<span class="delete text-danger" (click)="delete(tag)">
<i class="fas fa-trash-alt"></i>
</span>
</div>
The user interface:
We can use ViewChildren to get a hold of all the spans, by placing a template reference, pick up the span that is selected and set the focus to the element.
So I suggest adding template reference and in your beforeEdit() pass the index of the tag (we get it from ngFor), so we can refer to it when we want to place the focus on the field:
<!-- add template reference in below span tag --->
<span [contentEditable]="underUpdateTagId==tag.id" ... #spans>
<!-- pass index as from ngFor iteration to beforeEdit() -->
<span *ngIf="underUpdateTagId!=tag.id" class="edit text-info" (click)="beforeEdit(tag, i)">
<!-- more code --->
In the component we refer to spans, the template reference. And when clicked upon specify that the span with the index passed should be focused:
#ViewChildren("spans") spans: QueryList<ElementRef>;
underUpdateTagId = null;
beforeEdit(tag, index) {
this.underUpdateTagId = tag.id;
// wait a tick
setTimeout(() => {
this.spans.toArray()[index].nativeElement.focus();
});
}
STACKBLITZ
PS, this sets the focus in the beginning, you might want it at the end, maybe this question can help you with it if that is the case: Use JavaScript to place cursor at end of text in text input element
I have a div based on switch but the switch has a boolean variable but the value will be evaluated based on the row.id. Can some one tell me what I am doing wrong here ?
<div ng-switch="hasUrl">
<a ng-switch-when="row.id.indexOf(':') < 0 === true" href="{{url + row.id}}"> <!-- hasUrl = true -->
{{getName(row)}}
</a>
<a ng-switch-default href=".......">
{{getName(row)}}
</a>
</div>
You don't need the ===, remove it.
<div ng-switch="hasUrl">
<a ng-switch-when="row.id.indexOf(':') < 0" href="{{url + row.id}}"> <!-- hasUrl = true -->
{{getName(row)}}
</a>
<a ng-switch-default href=".......">
{{getName(row)}}
</a>
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 according to the docs take following example to solve your case:
<div ng-switch="hasUrl">
<span ng-switch-when="row.id.indexOf(':') < 0"> WONT SHOW </span> <!-- WILL NOT WORK EVER -->
<span ng-switch-when="makeItWork"> ALSO, WONT SHOW</span>
<span ng-switch-when="true">WILL NOT SHOW EITHER</span>
<span ng-switch-when="1">WILL SHOW</span>
</div>
Look carefullyat scope variables and their values:
$scope.hasUrl = 1; /* NOTICE != true BUT 1*/
$scope.row = {};
$scope.row.id = "true:";
$scope.makeItWork = $scope.row.id.indexOf(':') > 0 ? 1 : 0;
console.log($scope.makeItWork); /* SEE THAT TRUE WILL BE LOGGED BUT IT STILL WONT SHOW */
So even though ng-switch will evaluate an expression, it seems ng-switch-when wont. If I were you I would just stick to ng-if instead.
FIDDLE Fixed fiddle
I have a html span that display a date using moment.js in the page:
<span data-bind="text: moment(new Date(dueDate())).format('MM/DD/YYYY')"></span>
It's working fine apart if the dueDate() property is an empty string, If it's an empty string I'm getting:
01/01/1900
How can avoid that?
This is the entire div:
<div class="col-md-8">
<ul>
<li>DATE <span data-bind="text: moment(new Date(sDate())).format('MM/DD/YYYY')"></span></li>
<li>Due date <span></span><span data-bind="text: moment(new Date(dueDate())).format('MM/DD/YYYY')"></span>
<p>Days Remaining: <span class="days-remaining" data-bind="text: daysRemaining"></span></p>
</li>
<li>Date 2 <span></span><span data-bind="text: moment(new Date(date2())).format('MM/DD/YYYY')"></span>
<p>Days Remaining: <span class="days-remaining" data-bind="text: daysRemaining"></span></p>
</li>
</ul>
</div>
You will have to add a check. If value exists, then parse value, else show blank.
this.getDateInFormat = function(str){
var d = moment(str, DEFAULT_FORMAT);
return str && d.isValid() ? d.format('MM/DD/YYYY') : '';
}
As commented before, you should move all parsing logic to your viewModel. This way your code is generic and your view is clean.
JSFiddle.
In my MVC Razor project I am showing data in rows (list format).
These values are shown using javascript Knockout.
I want to higlight the selected row using javascript KnockoutJs.
Is there a better way of doing this.
Here is my code
<ul class="navlist" data-bind="foreach:selectOptions" >
<li><a href="#" data-bind="click:selectOption">
<span data-bind="text:name"></span>
<span data-bind="text:option"></span>
<span data-bind="text:optiondate"></span></a>
</li>
</ul>
I made a fiddle, it's pretty simple.
As you can see i store the the selected option in an observable.
And the databind applies the 'highlight' class if the selected option is the current option.
<ul class="navlist" data-bind="foreach:selectOptions" >
<li>
<div data-bind="click:$parent.selectOption, css: {'highlight' : $parent.selectedOption() == $data }" style="cursor: pointer">
<span data-bind="text:name"></span>
<span data-bind="text:option"></span>
<span data-bind="text:optiondate"></span>
</div>
</li>
</ul>
View model :
vm = {
selectOptions : [{name:'name1',option : 'option1', optiondate:'optiondate1'},
{name:'name1',option : 'option2', optiondate:'optiondate2'},
{name:'name3',option : 'option3', optiondate:'optiondate3'}],
selectOption : function(opt){
vm.selectedOption(opt);
},
selectedOption: ko.observable()
}
ko.applyBindings(vm);
I hope it helps.
I have posted something useful here:
Storing selected row in array in JavaScriptenter image description hereavascript/61581214#61581214
I would like to change from underscore template to mustache.js.
Since in mustache.js there are no if statements how can I change this piece of code in order to use mustache.js ?
<% if (done) { %>
<span class="todo-clear">
<a href="#">
Clear <span class="number-done"><%= done %></span>
completed <span class="word-done"><%= done === 1 ? 'item' : 'items' %></span>
</a>
</span>
<% } %>
My solution is:
{{#total}}
<span class="todo-count">{{ total }}
<span class="number">{{ remaining }}</span>
<span class="word"><%= remaining == 1 ? 'item' : 'items' %></span> left.-->
</span>
<span class="hint">
Drag tasks from one list into another and vice versa.
</span>
{{/total}}
It works for total variable, because it could be 0 or more, but I have no idea what is the best way to fix it on remaining variable, which could be 1 or more.
<span class="word"><%= remaining == 1 ? 'item' : 'items' %></span> left.</span>
It should be something like that:
<span class="word">
{{#remaining}} 'items' {{/remaining}}
{{^remaining}} 'item' {{/remaining}}
</span>
It does not work because remaining could be 1 or more.
In your view you could make something like this:
Mustache.render(yourTemplate, {
remaining: items.length > 1 ? true : false
}
If your just moving to a new templating framework, I would recommend using handlebars.js. This has support for if statements as follows:
{{#if total}}
<span>something</span>
{{else}}
<span>something else</span>
{{/if}}