天天看點

個人部落格設計:頁面問題總結(一)thymeleaf 局部重新整理頁面中,以及bootstrap4模态框的使用

本文采用thymeleaf模闆下使用bootstrap4。本人非前端,如有問題請指正,謝謝。

bootstrap4中文文檔可參考:http://bs4.ntp.org.cn/

直接上代碼,html部分:

<div class="container">   		
	<div class = "card-body">
		<div class="row">
			<div class="col-lg-2">
				<img src="/vendor/img/qq1.jpg" class="img-thumbnail">
			</div>
			<div class="col-lg-10">
				<div>
					<span class="text-secondary"style="font-size:17px;">ID:[[${profile.userId}]]</span>
				</div>		
				<div>
					<span style="margin-right:16px;">關注 1 </span><span>粉絲1</span>
				</div>
				<hr>
				<div class="commom-info">
					昵稱:<span>[[${profile.nickname}]]</span>
					<span id="mod-info" class="float-right text-primary" style="cursor:pointer"  data-toggle="modal" data-target="#accountModal">修改資料</span>
				</div>
                <!--  ...省略 -->
				
			</div>
		</div>
	</div>						
</div>
<!-- modal -->
<div class="modal fade" id="accountModal" tabindex="-1" role="dialog"	aria-labelledby="myModalLabel" aria-hidden="true">
  	<div class="modal-dialog">
		<div class="modal-content">
			<div class="modal-header">
				<h3 class="modal-title" id="myModalLabel">修改資訊</h3>
				<button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>	
			</div>
		    <div class="modal-body">
				<form id="updateForm" method="post" class="form-inline"> 				
    				<input id="userId" name="userId" type="hidden" th:value="${profile.userId}"/>				
			<div class="input-group input-group-sm col-lg-6" style="margin-bottom:1rem;">
				<label for="nickname" >昵稱:</label>													
    			<input id="nickname" name="nickname" type="text" class="form-control" th:value="${profile.nickname}" required/>			
			</div>
			<div class="col-12"></div>
   			<div class="input-group input-group-sm col-lg-4" style="margin-bottom:1rem;">
				<label for="sex" >性别:</label>													
    			<select id="sex" name="sex" class="form-control" th:value="${profile.sex}">	
    			    <option value="" style="display: none">未知</option>
    			    <option value="1" th:selected="${profile.sex==1}">男</option>
    			    <option value="0" th:selected="${profile.sex==0}">女</option>
    			</select>		
			</div>
			<div class="col-12"></div>
				<div class="col-lg-8 " onmouseover="addButton();" onmouseout="removeButton();">
					<div class="row">
   						<div id="datetimepicker" class="input-group input-group-sm date col-lg-9" style="margin-bottom:1rem;" >														
							<label for="birthday" >生日:</label>											
                    		<input id="birthday" name="birthday" type="text" class="form-control" th:value="${#dates.format(profile.birthday, 'yyyy-MM-dd')}"/> 
                    		<span class="input-group-append input-group-addon"  >
                        	    <i class="fa fa-calendar input-group-text" style="top:0px;" aria-hidden="true" ></i>
                    		</span>                                      														
						</div>
			     		<div class="col-lg-3" style="padding-left:0px;top:4px;">
                   			<i id="removeButton" class="glyphicon glyphicon-remove text-secondary" hidden="true" onclick="clearDate();"></i>
            			</div> 
					</div>  
           		</div> 	
				<div class="col-12"></div>
					<div class="input-group input-group-sm col-lg-6" style="margin-bottom:1rem;">
						<label for="occupation" >職業:</label>													
    					<input id="occupation" name="occupation" type="text" class="form-control" th:value="${profile.occupation}"/>			
					</div>
					<div class="col-12"></div>
				<div class="input-group input-group-sm col-lg-12" style="margin-bottom:1rem;">
					<label for="address" >位址:</label>																				
    					<select id="province" name="province" class="form-control" th:onchange="getCitys(this,'city');" style="margin-right:.5rem">
    						<option value="">--選擇省--</option>
							<option th:each="province:${map['provinces']}" th:value="${province.code}"  th:selected="${profile.province==province.code}">
										[[${province.name}]]
									</option>
    					</select>
    					<select id="city" name="city" class="form-control" th:onchange="getCitys(this,'county');" style="margin-right:.5rem">
    						<option value="">--選擇市--</option>
							<option th:each="city:${citys}" th:value="${city.code}"  th:selected="${profile.city==city.code}">
										[[${city.name}]]
									</option>
    					</select>
    					<select id="county" name="county" class="form-control" style="margin-right:.5rem">
    						<option value="">--選擇縣--</option>
    						<option th:each="county:${countys}" th:value="${county.code}"  th:selected="${profile.county==county.code}">
										[[${county.name}]]
									</option>								
    					</select>			
					</div>
					<div class="col-12"></div>
					<div class="input-group input-group-sm col-lg-12" style="margin-bottom:1rem;">
						<label for="brief" >簡介:</label>													
    					<textarea id="brief" name="brief"  class="form-control">[[${profile.brief}]]</textarea>		
					</div>
					<div class="col-12"></div>
				</form>
			</div>
		<div class="modal-footer">
			<button type="button" class="btn btn-secondary" data-dismiss="modal">關閉</button>
			<button type="button" name="submit" class="btn btn-primary" onclick="update();">送出更改</button>
			</div>
		</div>
	<!-- /.modal-content -->
	</div>
	<!-- /.modal -->
</div>		
           

先完成模态框的綁定,點選 立即修改 就會彈出。通過thymeleaf th:value屬性或者[[${data}]]來初始化背景傳輸的資料。

個人部落格設計:頁面問題總結(一)thymeleaf 局部重新整理頁面中,以及bootstrap4模态框的使用

這裡還有個問題,如果在模态框修改input值之後,沒有送出至背景,直接關閉模态框,再次打開時會是修改後的值,這樣顯示出的資料與原始資料有出入,使用者體驗不好,是以再每次打開對模态框的值進行初始化。上代碼:

<script th:inline="javascript">	
    $('#accountModal').on('show.bs.modal', function (e) {
		
		  $('#nickname').val([[${profile.nickname}]]);
		  $('#nickname').tooltip('dispose').removeClass('error');
		  $('#sex').val([[${profile.sex}]]);
		  $('#birthday').val([[${#dates.format(profile.birthday, 'yyyy-MM-dd')}]]);
		  $('#occupation').val([[${profile.occupation}]]);
		  $('#brief').val([[${profile.brief}]]);
		  $('#province').val([[${profile.province}]]);
		  getCitys($('#province'),'city');//這行代碼暫不考慮
		  $('#city').val([[${profile.city}]]);
		  getCitys($('#city'),'county');//這行代碼暫不考慮
		  $('#county').val([[${profile.county}]]);
		 
	});
</script>
           

‘show.bs.modal’是模态框打開之前觸發的事件,js中使用thymeleaf文法,務必加上 th:inline="javascript"。

考慮到每次修改完成後隻是更新使用者的資料,name重新整理整個頁面看起來就不那麼好了,是以本人采用局部重新整理。上網找了好久,網上推薦使用.load()方法。

$("#accountModal").modal('hide');
			$.ajax({
				type:'post',
				url:'/user/profile',
				contentType: 'application/json',
				data:JSON.stringify($('#updateForm').formToJSON()),
				success : 
					function(jsonData) {
						if(jsonData.success){
							$("div.modal-backdrop").remove();//有用
							$('#main-content').load("/user/profile/module");			
							return;
						}else {
							$("#tip").tooltip({
								title:jsonData.message,
								placement:"auto",
								template:'<div class="tooltip" role="tooltip"><div></div><div class="tooltip-inner"></div></div>'
							});
				 			$("#tip").tooltip("show");
				 			setTimeout(function(){
				 				$("#tip").tooltip('dispose');
				 			},1000);
							return;
						}
					},
			});
           

$('#main-content').load("/user/profile/module"); $('#main-content')為要重新整理的元素位置,load(url)将傳回的頁面渲染到main-content。是以load傳回的頁面也應該是原來的大小,也就是去除導航欄等等的,不然會出現俄羅斯套娃。

<div  id="main-content">
	   <div class="card" th:fragment="main-content">
        </div>
</div>
           

每次局部重新整理,這裡也就是重新整理main-content部分,頁面傳回的html就是th:fragment所包含的。後端代碼:

@GetMapping("/user/profile/module")
	public String module(Model model) {
		SysUser user = getUser();
		Profile profile = profileService.getById(user.getId());
		tranName(profile);
		Map<String, List<Object>> map = resourceRespository.getAllGroup(CnDivisionResourceLoaderImpl.LOADER);

		model.addAttribute("profile", profile);
		model.addAttribute("provinces", map.get("provinces"));
		model.addAttribute("citys", map.get(profile.getProvince()));
		model.addAttribute("countys", map.get(profile.getCity()));
		model.addAttribute("map", map);
		return "user/profile::main-content";
	}
           

"user/profile::main-content  其中user/profile是你要傳回的html的位置,main-content 為它内部th:fragment屬性所包含的内容。這樣就隻重新整理main-content部分,而不是整個頁面。該傳的參數還是用通過Model傳出。

前面代碼中提到的$("div.modal-backdrop").remove();//有用,這是因為.load局部重新整理的時候,由于頁面的沖突,有時候模态框的遮罩窗還沒又消失就頁面重新整理了,遮罩會覆寫在上層,是以手動清除。

由于局部重新整理時重新加載的元素,原來的綁定事件會失效,是以綁定的元件和插件都得重新綁定(本人不知道有什麼其他的解決方式),比如這裡使用的datetimepicke日期插件,局部重新整理後,打開模态框,月曆插件失效不顯示。是以采用jquery的.load(url,data,function),修改代碼如下:

<script th:inline="javascript">	
//隻有這部分代碼,局部重新整理後會失效
$('#datetimepicker').datetimepicker({
    language:  "zh-CN",
    format: "yyyy-mm-dd",//顯示格式
    minView: 2,//設定隻顯示到月份
    initialDate: new Date(),//初始化目前日期
    autoclose: true,//選中自動關閉
    todayBtn: true, //顯示今日按鈕
    pickerPosition: "bottom-left",   
});

$.ajax({
				type:'post',
				url:'/user/profile',
				contentType: 'application/json',
				data:JSON.stringify($('#updateForm').formToJSON()),
				success : 
					function(jsonData) {
						if(jsonData.success){
							$("div.modal-backdrop").remove();//消除遮罩
							$('.datetimepicker').remove();//消除上次的月曆元素,否則會一直添加新的,可以F12看看
							$('#main-content').load("/user/profile/module",function(){
								$('#datetimepicker').datetimepicker({
								    language:  "zh-CN",
								    format: "yyyy-mm-dd",//顯示格式
								    minView: 2,//設定隻顯示到月份
								    initialDate: new Date(),//初始化目前日期
								    autoclose: true,//選中自動關閉
								    todayBtn: true, //顯示今日按鈕
								    pickerPosition: "bottom-left",   
								});
							});			
							return;
						}else {
							$("#tip").tooltip({
								title:jsonData.message,
								placement:"auto",
								template:'<div class="tooltip" role="tooltip"><div></div><div class="tooltip-inner"></div></div>'
							});
				 			$("#tip").tooltip("show");
				 			setTimeout(function(){
				 				$("#tip").tooltip('dispose');
				 			},1000);
							return;
						}
					},
			});
</script>
           

這樣月曆插件也能正常使用了。

如果模态框不放在局部重新整理的頁面内,模态框綁定的插件能正常使用,但是模态框内的資料不會跟着重新整理。當然這裡應該有更好的方法,或者前端的其他架構有更好的處理方式,由于本人非前端,自己做頁面時自己摸索,如有問題歡迎讨論。如需轉載,請注明出處,敲代碼不容易啊。

繼續閱讀