KoGrid not displayed when Select also on page - asp.net-mvc-4

I have an ASP.Net MVC4 website. Here's the problem view:
#model TVS.ESB.BamPortal.Website.Models.MyTasksViewModel
#using System.Web.Script.Serialization
#{
ViewBag.Title = "My Tasks";
Layout = "~/Views/Shared/_Layout.cshtml";
}
<h2>#ViewBag.Title</h2>
#{ string data = new JavaScriptSerializer().Serialize(Model); }
<div id="Knockout">
#* When select added thenKoGrid does not display! <select class="form-control" data-bind="options:users, optionsText: 'AdLoginId', value:selectedUser" />*#
<div id="Buttons">
<span>Reassign to User: <input class="form-control" data-bind="text:username"/></span>
<button class="btn-default" data-bind="click:promoteState">Promote State</button>
<button class="btn-default" data-bind="click:reassignTasks">Reassign Task(s)</button>
</div>
<div id="KoGrid" data-bind="koGrid: gridOptions" />
</div>
#section Scripts {
<script src="~/KnockoutVM/Mytasks.js"></script>
<link rel="stylesheet" type="text/css" href="~/Content/KoGrid.css">
<script type="text/javascript">
var vm = new ViewModel(#Html.Raw(data));
ko.applyBindings(vm, document.getElementById("Knockout"));
</script>
}
I have commented out the select that gives the problem. If I leave this in, then it displays fine, including the items from the observeable array I'd expect. However, for some reason the KoGrid is then not displayed. If I remove the Select then the KoGrid displays just fine. I've tried refreshing with the Google dev tool console window open but no errors are reported. Any ideas why?
Here are relevant parts of the knockout view model:
function ViewModel(vm) {
var self = this;
this.myData = ko.observableArray(vm.Recs);
this.selected = ko.observableArray();
this.users = ko.observableArray(vm.Users);
this.selectedUser = ko.observable("");
this.username = ko.observable("");
this.rows = ko.observableArray(vm.Recs);
this.gridOptions = {
data: self.myData,
enablePaging: true,
pagingOptions: self.pagingOptions,
filterOptions: self.filterOptions,
selectWithCheckboxOnly: true,
selectedItems: self.selected,
canSelectRows: true,
displaySelectionCheckbox: true,
columnDefs: [{ field: 'Timestamp', displayName: 'Timestamp', width: 130 },
{ field: 'State', displayName: 'State', width: 70 },
{ field: 'FaultApplication', displayName: 'Application', width: 110 },
{ field: 'FaultExceptionMessage', displayName: 'Exception Message', width: 400 },
{ field: 'FaultServiceName', displayName: 'ServiceName', width: 140 },
{ field: 'LinkToFaultsPage', displayName: 'Link to Fault', width: 80, cellTemplate: '<a data-bind="attr: { href: $parent.entity.LinkToFaultsPage}" >Fault</a>' }
]
};
};

Your KOGrid is not displayed because your HTML is invalid:
The select tag cannot be self-closing see also on MDN.
So you need to always write out the closing tag </select>:
<select class="form-control"
data-bind="options:users,
optionsText: 'AdLoginId', value:selectedUser">
</select>
Otherwise the HTML is invalid and Knockout cannot interpret it properly.

I was able to work-around by moving the select list to a separate div and using the ko.applyBindings twice:
<div id="ControlPanel">
<select class="form-control" data-bind="options:users, optionsText: 'AdLoginId', value:selectedUser" />
<div id="Buttons">
<span>Reassign to User: <input class="form-control" data-bind="text:username" /></span>
<button class="btn-default" data-bind="click:promoteState">Promote State</button>
<button class="btn-default" data-bind="click:reassignTasks">Reassign Task(s)</button>
</div>
<div id="KoGrid" data-bind="koGrid: gridOptions" />
</div>
#section Scripts {
<script src="~/KnockoutVM/Mytasks.js"></script>
<link rel="stylesheet" type="text/css" href="~/Content/KoGrid.css">
<script type="text/javascript">
var vm = new ViewModel(#Html.Raw(data));
ko.applyBindings(vm, document.getElementById("ControlPanel"));
ko.applyBindings(vm, document.getElementById("KoGrid"));
</script>
}

Related

Vuelidate reset specific field so that $error flag is false

Using Vuelidate you can reset the validation errors by using this.$v.$reset(). In this Codepen example resetting the lastName field that uses a Vuetify component works - $invalid is true while $error is set to false.
When resetting the regular text input for firstName it doesn't work as the $error flag is still true. How can I modify the text input so that $error is false when calling reset?
I've also tried this.$nextTick(() => {...}) but that doesn't work either.
Vue.use(window.vuelidate.default)
var validationMixin = window.vuelidate.validationMixin
const {
maxLength,
required
} = window.validators
new Vue({
el: '#app',
mixins: [validationMixin],
data: () => ({
form: {
firstName: '',
lastName: ''
}
}),
validations: {
form: {
firstName: {
required, maxLength: maxLength(2)
},
lastName: {
required, maxLength: maxLength(2)
},
}
}
})
input.raw {
border: solid;
}
.is-invalid {
border-color: #FF5252 !important;
}
<html>
<head>
<script src="https://unpkg.com/vuelidate#0.6.1/dist/validators.min.js"></script>
<script src="https://unpkg.com/vuelidate#0.6.1/dist/vuelidate.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
</head>
<body>
<div id="app">
<label for="firstName">First Name</label>
<input
v-model="form.firstName"
id="firstName"
class="raw"
:class="{ 'is-invalid': $v.form.firstName.$error }"
type="text"
width="100%"
:oninput="$v.form.firstName.$touch()"
:onblur="$v.form.firstName.$touch()"
/>
<button #click="$v.form.firstName.$touch()">
$touch
</button>
<button #click="$v.form.firstName.$reset()">
$reset
</button>
<pre>{{ $v.form.firstName }}</pre>
</div>
</body>
</html>
In your example, you are using oninput and onblur HTML attributes, but in Vue, you should use #input(v-on:input) and #blur(v-on:blur) bindings instead. See docs for details.
Replacing HTML attributes with Vue bindings made your example work correctly:
Vue.use(window.vuelidate.default)
var validationMixin = window.vuelidate.validationMixin
const {
maxLength,
required
} = window.validators
new Vue({
el: '#app',
mixins: [validationMixin],
data: () => ({
form: {
firstName: '',
lastName: ''
}
}),
validations: {
form: {
firstName: {
required, maxLength: maxLength(2)
},
lastName: {
required, maxLength: maxLength(2)
},
}
}
})
input.raw {
border: solid;
}
.is-invalid {
border-color: #FF5252 !important;
}
<html>
<head>
<script src="https://unpkg.com/vuelidate#0.6.1/dist/validators.min.js"></script>
<script src="https://unpkg.com/vuelidate#0.6.1/dist/vuelidate.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
</head>
<body>
<div id="app">
<label for="firstName">First Name</label>
<input
v-model="form.firstName"
id="firstName"
class="raw"
:class="{ 'is-invalid': $v.form.firstName.$error }"
type="text"
width="100%"
#input="$v.form.firstName.$touch()"
#blur="$v.form.firstName.$touch()"
/>
<button #click="$v.form.firstName.$touch()">
$touch
</button>
<button #click="$v.form.firstName.$reset()">
$reset
</button>
<pre>{{ $v.form.firstName }}</pre>
</div>
</body>
</html>
This is Issue From Vuelidate and they must be fixed, in this position you can not reset form and give same (badly) behavior you can re-render by the router
// re render component for reset all fileds
this.$router.go(0)

Vue.js watched data chang twice with only one request

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title></title>
</head>
<body>
<div id="app">
<div class="layui-input-block" style="width:510px;">
<form class="layui-form" action="">
<select v-model="form.entrCode">
<option value="">please select an entry</option>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
</select>
</form>
</div>
</div>
</body>
</html>
<script src="//cdn.bootcss.com/vue/2.2.4/vue.min.js"></script>
<script type="text/javascript">
var app = new Vue({
el: "#app",
data: {
action: '',
form: {
entrCode: '',
}
},
watch: {
action: function (val) {
if (val !== "add"){
var vm = this;
//$.get("/park/GetLEDDtl", { areaId: vm.form.code }, function (rs) {
// vm.form = rs;
//}, "json");
//simulate setting on ajax.success
vm.form = { "entrCode": "20" };
}
},
"form.entrCode": function (val, old) {
alert("【entryCode changed】 new:" + val + " old:" + old);
}
},
created: function () {
this.action = "edit";
}
});
</script>
Please look at my code. I've only set app.form = object once, why there are two value changed be watched?
First, it changes from '' to '20', which is what I'm expected, but suddenly it changes from 20 to undefined.
(The code patsed I commented ajax request, and set value directly.)
What just happened?
There is no option with the value you are setting the variable to. The select object cannot be synced up to show the value, so it reverts the value to undefined.

Custom close button in datetimepicker form [duplicate]

$(function() {
$('input.month-mode').datetimepicker({
viewMode: 'months',
format: 'MM/YYYY',
showClose: true,
maxDate: current_month,
});
});
I want to add close text to it. by default it shows 'X', but I want to change it. Is it possible?
You can use icons option to define a custom css class for your icon and then you can write a css rule to customize close text as shown below:
$(function () {
var current_month = moment(); // just a sample value
$('#datetimepicker1').datetimepicker({
showClose: true,
viewMode: 'months',
format: 'MM/YYYY',
maxDate: current_month,
icons: {
close: 'closeText'
}
});
});
.closeText:before {
content: "Close";
}
<link href="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/css/bootstrap.css" rel="stylesheet"/>
<link href="//cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.7.14/css/bootstrap-datetimepicker.css" rel="stylesheet"/>
<script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/moment.js/2.12.0/moment.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.6/js/bootstrap.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.7.14/js/bootstrap-datetimepicker.min.js"></script>
<div class='input-group date' id='datetimepicker1'>
<input type='text' class="form-control" />
<span class="input-group-addon">
<span class="glyphicon glyphicon-calendar"></span>
</span>
</div>
One way to do this is to use the icon classes to a add a new class and then use css to add some content. Something like:
$(function() {
$('input.month-mode').datetimepicker({
viewMode: 'months',
format: 'MM/YYYY',
showClose: true,
maxDate: current_month,
icons: {
close: 'textclass1'
}
});
});
Css:
.textclass1::before {
content: "Close";
}

$routeProvider in AngularJs is not Working

I'm using angularJs and new to it. I'm facing problem in $routeProvider.
Thanks in advance if someone may help me :)
when i see in firebug it show reference not set for $routeProvider.
here is my code..
main.html.
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" ng-app="demoApp"><!--you can use data-ng-app directive also-->
<head>
<title>Using Directive With DataBinding</title>
<script src="Scripts/angular.min.js"></script>
<script>
//var demoApp = angular.module('demoApp', ['helperModule']);
var demoApp = angular.module('demoApp', []);
demoApp.config(function($routeProvider) {
$routeProvider
.when('/', {
controller: 'SimpleController',
templateUrl: 'View1.html'
})
.when('/view2', {
controller: 'SimpleController',
templateUrl: 'View2.html'
})
.otherwise({ redirectTo: '/' });
});
var controllers = {};
controllers.SimpleController = function ($scope) { // here $scope is dependency injection
$scope.customers = [
{ name: 'Sombir', city: 'Rohtak' },
{ name: 'Surender', city: 'Hissar' },
{ name: 'Virender', city: 'Panipat' },
{ name: 'Kapil', city: 'Jhajjar' }
];
$scope.addCustomer = function() {
$scope.customers.push(
{
name: $scope.newCustomer.name,
city: $scope.newCustomer.city
});
};
};
demoApp.controller(controllers);
</script>
</head>
<body>
<div>
<div data-ng-view=""><!--PlaceHolder for views--></div>
</div>
</body>
</html>
View1.html
-----------------
<div class="container">
Name:
<input type="text" ng-model="filter.name" /><!--you can use data-ng-model directive also-->
<h3>Adding A simple Controller --View1</h3>
<ul>
<li data-ng-repeat="cust in customers | filter:filter.name | orderBy:'city'">{{cust.name | uppercase}}---{{cust.city}}</li>
</ul>
<br/>
Customer Name:
<input type="text" ng-model="newCustomer.name"/>
Customer City:
<input type="text" ng-model="newCustomer.city" />
<br/>
<button ng-click="addCustomer()">Add Customer</button>
View2
</div>
You forgot to inject 'ngRoute' in your module 'demoApp' in your script tag
var demoApp = angular.module('demoApp', ['ngRoute']);

How to place checkboxes in a tree?

Can someone suggest how can I place check boxes against each folder of the below tree hierarchy? I am trying to add check-boxes but it is not showing up in my tree shown below. Please suggest the changes i need to make for my below code to get the checkbox displayed. This is a working code , just copy paste the same in a textpad and open in IE allowing activex.
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-type" content="text/html; charset=UTF-8"/>
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/dojo/1.7.2/dojo/resources/dojo.css">
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/dojo/1.7.2/dijit/themes/claro/claro.css">
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/dojo/1.7.2/dojox/grid/resources/Grid.css">
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/dojo/1.7.2/dojox/grid/resources/claroGrid.css">
<script src="http://ajax.googleapis.com/ajax/libs/dojo/1.7.2/dojo/dojo.js"
data-dojo-config="isDebug: true,parseOnLoad: true"></script>
<link rel="stylesheet" href="css/style.css" media="screen">
<script>
dojo.require("dojo.parser");
dojo.require("dijit.form.Form");
dojo.require("dijit.form.Select");
dojo.require("dijit.form.TextBox");
dojo.require("dijit.layout.BorderContainer");
dojo.require("dijit.layout.AccordionContainer");
dojo.require("dijit.layout.ContentPane");
dojo.require("dijit.layout.TabContainer");
dojo.require("dojo.data.ItemFileWriteStore");
dojo.require("dijit.tree.ForestStoreModel");
dojo.require("dijit.tree.dndSource");
dojo.require("dijit.Tree");
dojo.addOnLoad(function() {
dojo.byId('loaderInner').innerHTML += " done.";
setTimeout(function hideLoader(){
dojo.fadeOut({
node: 'loader',
duration:500,
onEnd: function(n){
n.style.display = "none";
}
}).play();
}, 250);
});
var store;
var selectedItemId = 0;
var itemSelected = null;
var sel = null;
var idCount = 0;
var treeModel;
var mytree;
var modeSelector;
dojo.ready(function(){
store = new dojo.data.ItemFileWriteStore({
contentType: 'application/json',
target: 'store',
url: "http://pmis.biz/rwa/data/ProjectList.php"
});
treeModel = new dijit.tree.ForestStoreModel({
iconClass: 'dijitEditorIcon dijitEditorIconCut',
store: store,
query: {"main": 0},
rootId: 0,
rootLabel: "project",
pasteItem: function(){},
mayHaveChildren : function(item) {
return true;
},
getChildren: function(parentItem, callback, onError) {
if(parentItem.root == true ){
if(this.root.children){
callback(this.root.children);
}else{
this.store.fetch({
query: this.query,
queryOptions: {cache:false},
onComplete: dojo.hitch(this, function(items){
this.root.children = items;
callback(items);
}),
onError: onError
});
}
} else {
console.debug("Tree child onLoad here: "+parentItem.id);
if (idCount < parseInt(parentItem.id)){
idCount = parseInt(parentItem.id);
}
var sx = parseInt(parentItem.id);
this.store.fetch({
query: { main: sx },
queryOptions: {cache:false},
onComplete: dojo.hitch(this, function(items){
this.root.children = items;
callback(items);
}),
onError: onError
});
}
}
});
mytree = new dijit.Tree({
model: treeModel,
openOnClick:true,
showRoot: true,
setCheckboxOnClick : true,
// onDblClick: function (item, node, evt){
// },
onClick: function (item, node, evt){
resetEditor();
}
}, "treeThree");
});
</script>
</head>
<body class="claro">
<!-- BorderContainer -->
<div id="main" data-dojo-type="dijit.layout.BorderContainer"
data-dojo-props="liveSplitters:false, design:'headline',
style:'width:100%; height:100%; max-width:1050px; min-width:680px; min-height:400px; margin: 0 auto;'">
<!-- AccordionContainer-->
<div data-dojo-type="dijit.layout.AccordionContainer"
data-dojo-props="region:'leading', splitter:true, minSize:20" style="width: 630px;" id="leftAccordion">
<div data-dojo-type="dijit.layout.ContentPane" data-dojo-props="title:'NG Tree Hierarchy'">
<div data-dojo-type="dijit.layout.ContentPane"
data-dojo-props="title:'Rootless Tree',
style:'width:30%; height:100%; max-width:1050px; min-width:250px; min-height:300px; margin: 0 auto; float:left'">
<div id="treeThree"></div>
</div>
<div data-dojo-type="dijit.layout.ContentPane" data-dojo-props="title:'Rootless CCCCCC'">
<!-- Project selector -->
<div id=help"></div><br>
<br>
<!-- <select id="f_2"></select>-->
<br>
<div>
<table style="width: 135px; height: 83px;">
<tr><td>
<div id="ip"></div>
</tr><tr><td>
<button id="bd" data-dojo-type="dijit.form.Button" style="visibility:hidden"
data-dojo-id="bd"
data-dojo-props="disabled: true,
onClick: function (evt){
store.deleteById(selectedItemId);
resetEditor();
},
label:'Delete project' ">
</button>
<button id="bs" data-dojo-type="dijit.form.Button" style="visibility:hidden"
data-dojo-id="bs"
data-dojo-props="disabled: true,
onClick: function (evt){
var lvalue = dijit.byId('s1').value;
store.setValue(itemSelected, 'title', dijit.byId('s1').value);
store.setValue(itemSelected, 'description', dijit.byId('s2').value);
store.save();
},
label:'Save project' ">
</button>
<button id="ba"data-dojo-type="dijit.form.Button" style="visibility:hidden"
data-dojo-id="ba"
data-dojo-props="disabled: true,
onClick: function (evt){
idCount = idCount +1;
var newItem = {};
newItem.id = idCount;
newItem.main = selectedItemId;
newItem.title = dijit.byId('s1').value;
newItem.description = dijit.byId('s2').value;
store.newItem(newItem);
sel.setStore(store,'',{query:{main: 0}});
/* mytree.update();*/
},
label:'Add project' ">
</button>
<br>
<button onclick="mytree.refreshModel()" style="visibility:hidden">
Update
</button>
</tr>
</table>
<br>
</div>
</div>
</div>
<div data-dojo-type="dijit.layout.ContentPane" data-dojo-props="title:''">
<div></div>
</div>
</div>
<div id="header" data-dojo-type="dijit.layout.ContentPane" data-dojo-props="region:'top'">
</div>
<!-- Top tabs (marked as "center" to take up the main part of the BorderContainer) -->
<div data-dojo-type="dijit.layout.TabContainer" data-dojo-props="region:'center', tabStrip:true" id="topTabs">
<div id="basicFormTab1" data-dojo-type="dijit.layout.ContentPane"
data-dojo-props="title:'Tab1', style:'padding:10px;display:none;'">
<p> </p>
</div>
<div id="basicFormTab2" data-dojo-type="dijit.layout.ContentPane"
data-dojo-props="title:'Tab2', style:'padding:10px;display:none;'">
<p> </p>
</div>
<div id="basicFormTab3" data-dojo-type="dijit.layout.ContentPane"
data-dojo-props="title:'Tab3', style:'padding:10px;display:none;'">
<p> </p>
</div>
</div>
</div>
</body>
</html>
A library was created for this:
http://www.thejekels.com/dojo/cbtree_AMD.html
The instruction manual is kind of hard to find from that site. It is a github wiki here: https://github.com/pjekel/cbtree/wiki/CheckBox-Tree. Download the git repo, then follow instructions at https://github.com/pjekel/cbtree/wiki/Installation, and you should be good to go.
Try this one (tested on dojo 1.10):
require(["dojo/_base/connect", "dijit/dijit", "dojo/data/ItemFileReadStore", "dijit/Tree", "dijit/form/CheckBox",
"dojo/domReady!"],
function (connect, dijit, ItemFileReadStore, Tree, CheckBox) {
var store = new ItemFileReadStore({
data: {
identifier: 'id',
label: 'label',
items: rawdata
}
});
var treeControl = new Tree({
store: store,
showRoot: false,
_createTreeNode: function (args) {
var tnode = new Tree._TreeNode(args);
tnode.labelNode.innerHTML = args.label;
var cb = new CheckBox();
cb.placeAt(tnode.labelNode, "first");
connect.connect(cb, "onChange", function () {
var treeNode = dijit.getEnclosingWidget(this.domNode.parentNode);
connect.publish("/checkbox/clicked", [{
"checkbox": this,
"item": treeNode.item
}]);
});
return tnode;
}
}, "CheckboxTree");
connect.subscribe("/checkbox/clicked", function (message) {
console.log("you clicked:", store.getLabel(message.item));
});
}); // require
var rawdata = [{
label: 'Level 1',
id: '1',
children: [{
label: 'Level 1.1',
id: '1.1',
active: true
},
{
label: 'Level 1.2',
id: '1.2',
active: true
}]
},
{
label: 'Level 2',
id: '2',
children: [{
id: '2.1',
label: 'Level 2.1',
active: false
},
{
id: '2.2',
label: 'Level 2.2',
active: true
},
{
id: '2.3',
label: 'Level 2.3',
active: true
}]
}];