I am having the following issue. I have a mini SPA with an option to view products, edit and create.
The SPA I created using the default .aspx page that comes when you add a new Item (Page), into a sharepoint hosted app, this .aspx files come with some markup and they use default.master
In one of my views I have a form, with an ng-click event to save the data locally into my array of products.
The code is not throwing any exception, however I noticed that when using the .aspx page instead of a plain .html page ASP.NET renders another form tag around the entire sharepoint hostead app, and we all know that there can only be a form per page, right? As a result when I use default.aspx my angular js form is stripped out and therefor my ng-click is doing a postback (because the parent form element has runat=server I suppose), and even if the submit method in the controller is called, then my local data is lost after the postback.
This was already asked here but no good answer for me: 2013: How can I use a form in my AngularJS code in the Default.aspx page?
So, there are 2 possibilities: 1. How can I add the sharepoint suitebar links look and feel to a .html file and still keep my angularjs-controlled form working? 2. Is there anyway to remove the aspnet form rendered by Sharepoint in Sharepoint hosted apps?
I paste here the most relevant pieces of my code just for reference as its too long
Index.html
<!doctype html>
<html>
<head>
<!-- Styles -->
<link href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" rel="stylesheet" />|
<link href="../Content/App.css" rel="stylesheet" />
<!-- Common Libraries -->
<script src="//code.jquery.com/jquery-2.1.1.min.js" type="text/javascript"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.3.2/angular.min.js" type="text/javascript"></script>
<script src="//code.angularjs.org/1.3.2/angular-resource.min.js" type="text/javascript"></script>
<script src="//code.angularjs.org/1.3.2/angular-mocks.js" type="text/javascript"></script>
<script src="../Scripts/lib/angular-ui-router.min.js" type="text/javascript"></script>
<script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.11.2.js" type="text/javascript"></script>
<script src="../Scripts/lib/ui-utils.min.js" type="text/javascript"></script>
<!-- Application Script -->
<script src="../Scripts/App/App.js" type="text/javascript"></script>
<!-- Services -->
<script src="../Scripts/App/Common/Services/common.services.js" type="text/javascript"></script>
<script src="../Scripts/App/Common/Services/productResource.js" type="text/javascript"></script>
<script src="../Scripts/App/Common/Services/productResourceMock.js" type="text/javascript"></script>
<!--Controllers -->
<script src="../Scripts/App/Products/ProductListCtrl.js" type="text/javascript"></script>
<script src="../Scripts/App/Products/productDetailCtrl.js" type="text/javascript"></script>
<script src="../Scripts/App/Products/productEditCtrl.js" type="text/javascript"></script>
</head>
<body ng-app="productManagement">
<nav class="navbar navbar-inverse">
<div class="container">
<a class="navbar-brand"
ui-sref="home">Acme Product Management</a>
<div class="navbar-header">
<button type="button"
class="navbar-toggle"
data-toggle="collapse"
data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<div class="navbar-collapse collapse">
<ul class="nav navbar-nav">
<li><a ui-sref="productList">Product List</a></li>
<li>
<a ui-sref="productEdit.info({productId:0})">
<i class="glyphicon glyphicon-plus"></i>
Add Product
</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container">
<div ui-view></div>
</div>
</body>
</html>
ProductEditInfoView.html
<form class="form-horizontal" name="productForm">
<fieldset>
<legend>Basic Product Information</legend>
<div class="form-group">
<label class="col-md-2 control-label"
for="inputProductName">Product Name</label>
<div class="col-md-4">
<input class="form-control"
id="inputProductName"
type="text"
placeholder="Product Name"
ng-model="vm.product.productName" />
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label" for="inputProductCode">Product Code</label>
<div class="col-md-4">
<input class="form-control"
id="inputProductCode"
ui-mask="AAA-****"
ng-model="vm.product.productCode">
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label"
for="inputAvailabilityDate">Availability</label>
<div class="col-md-4">
<div class="input-group">
<input class="form-control"
id="inputAvailabilityDate"
type="text"
datepicker-popup="MMM dd, yyyy "
is-open="vm.opened"
ng-model="vm.product.releaseDate" />
<span class="input-group-btn">
<button class="btn btn-default"
ng-click="vm.open($event)">
<i class="glyphicon glyphicon-calendar" />
</button>
</span>
</div>
</div>
</div>
<div class="form-group">
<label class="col-md-2 control-label"
for="inputDescription">Description</label>
<div class="col-md-10">
<textarea class="form-control"
id="inputDescription"
placeholder="Description"
rows="3"
ng-model="vm.product.description" />
</div>
</div>
<div class="form-group">
<div class="col-md-4 col-md-offset-2">
<span>
<button class="btn btn-primary"
style="width:80px;margin-right:10px"
ng-click="vm.submit()">
Save
</button>
</span>
<span>
<button class="btn btn-default"
style="width:70px"
ng-click="vm.cancel()">
Cancel
</button>
</span>
</div>
</div>
</fieldset>
</form>
And ProductController with the submit!(which has a save !
(function () {
"use strict";
angular
.module("productManagement")
.controller("ProductEditCtrl",
["product",
"$state",
ProductEditCtrl]);
function ProductEditCtrl(product, $state) {
var vm = this;
vm.product = product;
if (vm.product && vm.product.productId) {
vm.title = "Edit: " + vm.product.productName;
}
else {
vm.title = "New Product"
}
vm.open = function ($event) {
$event.preventDefault();
$event.stopPropagation();
vm.opened = !vm.opened;
};
vm.submit = function () {
vm.product.$save();
}
vm.cancel = function () {
$state.go('productList');
}
vm.addTags = function (tags) {
if (tags) {
var array = tags.split(',');
vm.product.tags = vm.product.tags ? vm.product.tags.concat(array) : array;
vm.newTags = "";
} else {
alert("Please enter one or more tags separated by commas");
}
}
vm.removeTag = function (idx) {
vm.product.tags.splice(idx, 1);
}
}
}());