chrome console 出現這類錯誤 : POST http://localhost:9032/webservice1.asmx/GetActivitys 500 (Internal Server Error)
觀察server 事件檢視器會發現更明確的警告 :
Exception type: ArgumentOutOfRangeException
Exception message: 在多位元組的目的字碼頁中,沒有這個 Unicode 字元可以對應到的字元。 (發生例外狀況於 HRESULT: 0x80070459)
爬文得知是因為 cookie 中包含中文,會影響 jquery 的 $.ajax 功能
結論 : cookie 請勿使用中文,不管是 name 還是 value 都不行
2016年1月27日 星期三
2016年1月21日 星期四
angularjs 正確顯示 html
javascript
====
controller 注入 $sce
透過 $sce.trustAsHtml() 得到可以正確顯示的內容
html
====
<span ng-bind-html='content'></span>
====
controller 注入 $sce
透過 $sce.trustAsHtml() 得到可以正確顯示的內容
html
====
<span ng-bind-html='content'></span>
2016年1月18日 星期一
ag-grid 使用範例
//宣告
agGrid.initialiseAgGridWithAngular1(angular);
angular.module('module1', ['agGrid']).controller('ctrl1', function ($scope, $http, $filter) {
//初始設定
$scope.gridOptions = {
enableFilter: true, floatingFilter: true, suppressMenu: true, // 加入即時篩選方塊
suppressMovableColumns: true,
angularCompileRows: true,
rowSelection: 'single',
enableColResize: true,
enableSorting: true,
onCellFocused: function (event) {
if ($scope.gridOptions.api.getModel().rowsToDisplay[event.rowIndex]) $scope.gridOptions.api.getModel().rowsToDisplay[event.rowIndex].setSelected(true);
}, // 使用鍵盤方向鍵自動選取列
defaultColDef: {
suppressMenu: true, floatingFilterComponentParams: { suppressFilterButton: true } // 使用即時篩選方塊時隱藏不要顯示的物件
},
columnDefs: [
{
headerName: '日期', width: 100, cellStyle: { 'text-align': 'center'}, cellRenderer: function (params) {
return $filter('date')(new Date(params.value), 'yyyy/MM/dd');
},filter: 'agTextColumnFilter', filterParams: {
textCustomComparator: function (filter, value, filterText) {
var datestring = $filter('date')(new Date(value), 'yyyyMMdd');
return datestring.indexOf(filterText) >= 0;
}, // 日期篩選要透過客製化達成
}
},
※ 避免在 cellRenderer 中執行非 return 指令,避免畫面無法自動更新而必須透過 redrawrows 引發其他問題
//寫入資料
$scope.getlist = function () {
$http.post('@Url.Action("查詢")', { fromdate: $scope.fromdate, todate: $scope.todate })
.then(function (result) {
$scope.gridOptions.api.setRowData(result.data);
}).catch(function (data) {
if (data.status != '') alert(data.statusText);
else alert('發生錯誤,請重新整理頁面後再試一次');
console.log(data.data);
});
};
//html
<script type="text/javascript" src="~/scripts/ag-grid.min.js"></script>
<link href="~/Content/ag-grid.min.css" rel="stylesheet" type="text/css" />
<link href="~/Content/theme-fresh.min.css" rel="stylesheet" type="text/css" />
<div id="divlist" ag-grid="gridOptions" class="ag-fresh" ng-style="getTableHeight()"></div>
//css
讓 form-control 佔滿全部寬度
.ag-cell > span {
width: 100%;
}
避免cell使用 div 內含<br>時造成空隙太大
.ag-cell {
line-height: unset !important;
}
垂直置中 (有設定高度會需要)
.ag-cell {
display: flex !important;align-items: center;
}
.ag-header-cell-label {
width: 100% !important; // 避免欄位名稱要設定很寬否則顯示不完全而出現...
justify-content: center; // 置中
}
欄位左右間距調整
.ag-header-cell, .ag-header-group-cell, .ag-cell {
padding-left: 5px;
padding-right: 5px;
}
不要強制設定字型
點選欄位不要出現外框
agGrid.initialiseAgGridWithAngular1(angular);
angular.module('module1', ['agGrid']).controller('ctrl1', function ($scope, $http, $filter) {
//初始設定
$scope.gridOptions = {
enableFilter: true, floatingFilter: true, suppressMenu: true, // 加入即時篩選方塊
suppressMovableColumns: true,
angularCompileRows: true,
rowSelection: 'single',
enableColResize: true,
enableSorting: true,
onCellFocused: function (event) {
if ($scope.gridOptions.api.getModel().rowsToDisplay[event.rowIndex]) $scope.gridOptions.api.getModel().rowsToDisplay[event.rowIndex].setSelected(true);
}, // 使用鍵盤方向鍵自動選取列
defaultColDef: {
suppressMenu: true, floatingFilterComponentParams: { suppressFilterButton: true } // 使用即時篩選方塊時隱藏不要顯示的物件
},
columnDefs: [
{
headerName: '日期', width: 100, cellStyle: { 'text-align': 'center'}, cellRenderer: function (params) {
return $filter('date')(new Date(params.value), 'yyyy/MM/dd');
},filter: 'agTextColumnFilter', filterParams: {
textCustomComparator: function (filter, value, filterText) {
var datestring = $filter('date')(new Date(value), 'yyyyMMdd');
return datestring.indexOf(filterText) >= 0;
}, // 日期篩選要透過客製化達成
}
},
※ 避免在 cellRenderer 中執行非 return 指令,避免畫面無法自動更新而必須透過 redrawrows 引發其他問題
//寫入資料
$scope.getlist = function () {
$http.post('@Url.Action("查詢")', { fromdate: $scope.fromdate, todate: $scope.todate })
.then(function (result) {
$scope.gridOptions.api.setRowData(result.data);
}).catch(function (data) {
if (data.status != '') alert(data.statusText);
else alert('發生錯誤,請重新整理頁面後再試一次');
console.log(data.data);
});
};
//html
<script type="text/javascript" src="~/scripts/ag-grid.min.js"></script>
<link href="~/Content/ag-grid.min.css" rel="stylesheet" type="text/css" />
<link href="~/Content/theme-fresh.min.css" rel="stylesheet" type="text/css" />
<div id="divlist" ag-grid="gridOptions" class="ag-fresh" ng-style="getTableHeight()"></div>
//css
讓 form-control 佔滿全部寬度
.ag-cell > span {
width: 100%;
}
避免cell使用 div 內含<br>時造成空隙太大
.ag-cell {
line-height: unset !important;
}
垂直置中 (有設定高度會需要)
.ag-cell {
display: flex !important;align-items: center;
}
.ag-header-cell-label {
width: 100% !important; // 避免欄位名稱要設定很寬否則顯示不完全而出現...
justify-content: center; // 置中
}
欄位左右間距調整
.ag-header-cell, .ag-header-group-cell, .ag-cell {
padding-left: 5px;
padding-right: 5px;
}
不要強制設定字型
.ag-theme-balham,.ag-header {
font-size: unset !important;
}
點選欄位不要出現外框
.ag-cell-focus {
border: unset;
}
若用到 display: flex,且未使用cellRenderer,則水平靠右對齊方式改為
cellStyle: { 'justify-content': 'flex-end' }
計算筆數
$scope.gridOptions.api.getDisplayedRowCount(); // 篩選後筆數
$scope.gridOptions.api.getModel().rootNode.allLeafChildren.length; // 完整筆數
若用到 display: flex,且未使用cellRenderer,則水平靠右對齊方式改為
cellStyle: { 'justify-content': 'flex-end' }
計算筆數
$scope.gridOptions.api.getDisplayedRowCount(); // 篩選後筆數
$scope.gridOptions.api.getModel().rootNode.allLeafChildren.length; // 完整筆數
取得nodes (不要直接抓 rowData)
$scope.gridOptions.api.getModel().rowsToDisplay
Enumerable.From($scope.gridOptions.api.getModel().rowsToDisplay).Select('$.data').ToArray(); // 取data
若 cellRenderer 使用 {{}} 顯示內容,有些情況會造成沒有確實轉換,此時可以透過以下方式解決
$timeout(function () {
if (!$scope.$$phase) $scope.$apply();
}, 100);
載入資料後某欄位沒有任何資料則不顯示避免無用欄位太多
Enumerable.From($scope.gridOptions.columnDefs).ForEach(function (col) {
$scope.gridOptions.columnApi.setColumnVisible(col.field, Enumerable.From($scope.gridOptions.rowData).Any('$.'+col.field+''));
});
排序依照中文筆畫
{ field: '名稱', headerName: '名稱', comparator: textComparator },
function textComparator(a, b, d1, d2, isInverted) {
return a.localeCompare(b, "zh-Hant");
}
避免凍結欄位時出現捲軸
.ag-pinned-left-cols-viewport {
overflow-y: hidden !important;
}
Enumerable.From($scope.gridOptions.api.getModel().rowsToDisplay).Select('$.data').ToArray(); // 取data
若 cellRenderer 使用 {{}} 顯示內容,有些情況會造成沒有確實轉換,此時可以透過以下方式解決
$timeout(function () {
if (!$scope.$$phase) $scope.$apply();
}, 100);
載入資料後某欄位沒有任何資料則不顯示避免無用欄位太多
Enumerable.From($scope.gridOptions.columnDefs).ForEach(function (col) {
$scope.gridOptions.columnApi.setColumnVisible(col.field, Enumerable.From($scope.gridOptions.rowData).Any('$.'+col.field+''));
});
排序依照中文筆畫
{ field: '名稱', headerName: '名稱', comparator: textComparator },
function textComparator(a, b, d1, d2, isInverted) {
return a.localeCompare(b, "zh-Hant");
}
避免凍結欄位時出現捲軸
.ag-pinned-left-cols-viewport {
overflow-y: hidden !important;
}
2016年1月5日 星期二
取得 webapp 網址根路徑
Request.Url.Scheme + "://" + Request.Url.Authority + Request.ApplicationPath.TrimEnd('/') + "/"
於 angularjs 中下載及上傳檔案的方式 (支援多個檔案上傳)
1. server 產生檔案並下載 (epplus 為例)
c#
====
using (var ep = new OfficeOpenXml.ExcelPackage())
{
...
ep.Save();
return File((ep.Stream as System.IO.MemoryStream).ToArray(), "application/octet-stream");
}
javascript
====
$http({
url: urlBase + '/download',
method: "POST",
responseType: "blob",
data: { },
})
.then(function (result) {
downloadBlob(result.data, 'aaa.xlsx');
});
function downloadBlob(blob, name) {
if (ismobile()) { // iphone 無法使用 blob 下載,須轉為base64(上限2MB 且必須使用內建瀏覽器否則檔名會不正確)
var reader = new FileReader();
reader.readAsDataURL(blob);
reader.onloadend = function () {
var base64data = reader.result;
var link = document.createElement("a");
link.download = name;
link.href = base64data;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
delete link;
}
} else {
var link = document.createElement("a");
var url = URL.createObjectURL(blob);
link.download = name;
link.href = url;
document.body.appendChild(link);
link.onclick = function () {
requestAnimationFrame(function () {
URL.revokeObjectURL(url);
document.body.removeChild(link);
delete link;
})
};
link.click();
}
}
2. 上傳後下載
html
====
<input type="file" fileread="file" /> // 單一檔案上傳
<input type="file" multiple filesread="files" /> // 多重檔案上傳
javascript
====
$http.post('...', { filename: $scope.file.name,filecontent:$scope.file.value} // 單一檔案上傳
$http.post('...', { files: $scope.files} // 多重檔案上傳
c#
====
using (var ep = new OfficeOpenXml.ExcelPackage())
{
...
ep.Save();
return File((ep.Stream as System.IO.MemoryStream).ToArray(), "application/octet-stream");
}
javascript
====
$http({
url: urlBase + '/download',
method: "POST",
responseType: "blob",
data: { },
})
.then(function (result) {
downloadBlob(result.data, 'aaa.xlsx');
});
function downloadBlob(blob, name) {
if (ismobile()) { // iphone 無法使用 blob 下載,須轉為base64(上限2MB 且必須使用內建瀏覽器否則檔名會不正確)
var reader = new FileReader();
reader.readAsDataURL(blob);
reader.onloadend = function () {
var base64data = reader.result;
var link = document.createElement("a");
link.download = name;
link.href = base64data;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
delete link;
}
} else {
var link = document.createElement("a");
var url = URL.createObjectURL(blob);
link.download = name;
link.href = url;
document.body.appendChild(link);
link.onclick = function () {
requestAnimationFrame(function () {
URL.revokeObjectURL(url);
document.body.removeChild(link);
delete link;
})
};
link.click();
}
}
2. 上傳後下載
html
====
<input type="file" fileread="file" /> // 單一檔案上傳
<input type="file" multiple filesread="files" /> // 多重檔案上傳
javascript
====
$http.post('...', { filename: $scope.file.name,filecontent:$scope.file.value} // 單一檔案上傳
$http.post('...', { files: $scope.files} // 多重檔案上傳
).then(function (result) {
$('input[type=file]').val(''); // 清空選擇檔案內容
return {
scope: {
filesread: "="
},
link: function (scope, element, attributes) {
element.bind("change", function (changeEvent) {
scope.filesread = [];
Enumerable.From(changeEvent.target.files).ForEach(file => {
var reader = new FileReader();
var filename = file.name;
reader.onload = function (loadEvent) {
scope.$apply(function () { // $apply可確保真的更新,否則必須畫面有變化才會更新
scope.filesread.push({ name: filename, value: loadEvent.target.result }); // 對應到$scope.files
});
}
reader.readAsDataURL(file);
});
});
}
}
}])
c#
====
public class 檔案
{
public string name { get; set; }
public string value { get; set; }
}
public void 上傳(IEnumerable<檔案> files) {
var bytes = System.Text.Encoding.ASCII.GetBytes(檔案.value);
db.上傳檔案.Add(new 上傳檔案() { 檔案內容 = bytes, 檔名 = 檔案.name });
}
public string 下載檔案(int id)
{
var model = db.上傳檔案.Find(id);
return JsonConvert.SerializeObject(new { model.檔名, 檔案內容 = System.Text.Encoding.ASCII.GetString(model.檔案內容) });
}
javascript
====
$scope.download = function (id) {
$http.post(urlBase + '/下載檔案', { id: id }).then(function (result) {
downloadURI(result.data.檔案內容, result.data.檔名);
});
}
function downloadURI(dataURI, name) {
var link = document.createElement("a");
if (ismobile()) { // iphone 無法使用 blob 下載 (此寫法上限2MB 且必須使用內建瀏覽器否則檔名會不正確)
link.download = name;
link.href = dataURI;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
delete link;
}
else {
var blob = dataURIToBlob(dataURI);
var url = URL.createObjectURL(blob);
link.download = name;
link.href = url;
document.body.appendChild(link);
link.onclick = function () {
requestAnimationFrame(function () {
URL.revokeObjectURL(url);
document.body.removeChild(link);
delete link;
})
};
link.click();
}
}
function dataURIToBlob(dataURI) {
var binStr = atob(dataURI.split(',')[1]),
len = binStr.length,
arr = new Uint8Array(len),
mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]
for (var i = 0; i < len; i++) {
arr[i] = binStr.charCodeAt(i);
}
return new Blob([arr], {
type: mimeString
});
}
directive("fileread", [function () { // 單一檔案上傳
return {
scope: {
fileread: "="
},
link: function (scope, element, attributes) {
element.bind("change", function (changeEvent) {
var reader = new FileReader();
var filename = changeEvent.target.files[0].name;
reader.onload = function (loadEvent) {
scope.$apply(function () {
scope.fileread = { value: loadEvent.target.result, name: filename}; // 對應到$scope.file
});
}
reader.readAsDataURL(changeEvent.target.files[0]);
});
}
}
}])
directive("filesread", [function () { // 多重檔案上傳return {
scope: {
filesread: "="
},
link: function (scope, element, attributes) {
element.bind("change", function (changeEvent) {
scope.filesread = [];
Enumerable.From(changeEvent.target.files).ForEach(file => {
var reader = new FileReader();
var filename = file.name;
reader.onload = function (loadEvent) {
scope.$apply(function () { // $apply可確保真的更新,否則必須畫面有變化才會更新
scope.filesread.push({ name: filename, value: loadEvent.target.result }); // 對應到$scope.files
});
}
reader.readAsDataURL(file);
});
});
}
}
}])
c#
====
public class 檔案
{
public string name { get; set; }
public string value { get; set; }
}
public void 上傳(IEnumerable<檔案> files) {
foreach (var 檔案 in files)
{var bytes = System.Text.Encoding.ASCII.GetBytes(檔案.value);
db.上傳檔案.Add(new 上傳檔案() { 檔案內容 = bytes, 檔名 = 檔案.name });
}
public string 下載檔案(int id)
{
var model = db.上傳檔案.Find(id);
return JsonConvert.SerializeObject(new { model.檔名, 檔案內容 = System.Text.Encoding.ASCII.GetString(model.檔案內容) });
}
javascript
====
$scope.download = function (id) {
$http.post(urlBase + '/下載檔案', { id: id }).then(function (result) {
downloadURI(result.data.檔案內容, result.data.檔名);
});
}
function downloadURI(dataURI, name) {
var link = document.createElement("a");
if (ismobile()) { // iphone 無法使用 blob 下載 (此寫法上限2MB 且必須使用內建瀏覽器否則檔名會不正確)
link.download = name;
link.href = dataURI;
document.body.appendChild(link);
link.click();
document.body.removeChild(link);
delete link;
}
else {
var blob = dataURIToBlob(dataURI);
var url = URL.createObjectURL(blob);
link.download = name;
link.href = url;
document.body.appendChild(link);
link.onclick = function () {
requestAnimationFrame(function () {
URL.revokeObjectURL(url);
document.body.removeChild(link);
delete link;
})
};
link.click();
}
}
function dataURIToBlob(dataURI) {
var binStr = atob(dataURI.split(',')[1]),
len = binStr.length,
arr = new Uint8Array(len),
mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0]
for (var i = 0; i < len; i++) {
arr[i] = binStr.charCodeAt(i);
}
return new Blob([arr], {
type: mimeString
});
}
訂閱:
文章 (Atom)
input 連結 datalist 用程式控制彈出選項
範例: nextTick(() => document.querySelector('input').showPicker()); ※僅支援現代瀏覽器
-
1. 設定檔案下載儲存位置為 C:\Users\%username%\AppData\Local\Google\Chrome\User Data\Default\Cache 2. 勾選"下載每個檔案前詢問儲存位置" 3. 針對不要下載的檔案類型於第一...
-
自動設定欄寬 sheet.Cells.AutoFitColumns(3, 20); // 必須設定 min 跟 max 才會正常作用 凍結欄位 sheet.View.FreezePanes(4, 4); 標題列 ws.PrinterSettings.RepeatRo...
-
使用 FreeSpire.XLS ... ep.Save(); using (var workbook = new Workbook()) using (var memStream = new MemoryStream()) { workbook.LoadFromSt...