I want to display my database data into ionic view.
here detail data in my database:
{firstName: "John", lastName: "Doe", username: "jhondoe"}
my code in page controller:
import { AngularFireDatabase, FirebaseObjectObservable } from 'angularfire2/database';
profile : FirebaseObjectObservable<Profile>;
this.afAuth.authState.subscribe(data => {
if(data.email && data.uid){
this.afDatabase.object(`profile/${data.uid}`).valueChanges().subscribe(profile => {
this.profile = profile;
console.log(profile);
});
});
view page:
<ion-content padding>
<p>Username: {{ profile?.username | async }}</p>
<p>First Name: {{ profile?.firstName | async }}</p>
<p>Last Name: {{ profile?.LastName | async }}</p>
</ion-content>
but it not work, and display error:
InvalidPipeArgument: 'John' for pipe 'AsyncPipe'
profile is not a promise/observable since you are setting data after subscription here:
this.afDatabase.object(`profile/${data.uid}`).valueChanges().subscribe(profile => {
this.profile = profile;
console.log(profile);
});
Either declare profile as a regular object and remove async:
profile : Profile;
Html:
<p>Username: {{ profile?.username }}</p>
<p>First Name: {{ profile?.firstName}}</p>
<p>Last Name: {{ profile?.LastName}}</p>
OR.
declare as an observable and do not subscribe in ts.
profile : Observable<Profile>;
this.profile = this.afDatabase.object(`profile/${data.uid}`).valueChanges();
Related
I have a form with 3 inputs, 2 of the inputs are required and the third isn't.
My problem is that when I go the page of the form I see that the field that isn't required is in a valid state and is already colored with green, even tho the field isn't dirty or touched.
Is there anything I can do to make the input be grayed out until I validate the field / form or is it like this by design?
Here's the code I use in the component:
export class SystemSettingsComponent implements OnInit {
form: FormGroup;
constructor(private formBuilder: FormBuilder) {
this.form = new FormGroup({});
}
ngOnInit() {
this.form = this.formBuilder.group({
serviceName: ['', Validators.required],
serviceDesc: [''],
serviceId: [{value: SystemSettingsComponent.generateId(), disabled: true}, Validators.required]
});
}
static generateId() {
return Math.random().toString(36).substr(2, 9);
}}
And the template :
<form [formGroup]="form" novalidate>
<div class="row">
<div class="col-lg-4">
<mat-form-field>
<input matInput placeholder="שם השירות" formControlName="serviceName"/>
</mat-form-field>
<mat-form-field>
<textarea matInput placeholder="תיאור השירות" formControlName="serviceDesc"></textarea>
</mat-form-field>
<mat-form-field>
<input matInput class="ltr text-align-left" placeholder="מזהה שירות" formControlName="serviceId"/>
</mat-form-field>
</div>
</div>
<div>
<button mat-raised-button class="mat-raised-button mat-primary" matStepperNext>הבא</button>
</div>
You can listen to the form's status changes and set the optional form control's disabled state accordingly. Something like:
ngOnInit() {
this.form = this.formBuilder.group({
serviceName: ['', Validators.required],
serviceDesc: [{value: '', disabled: true}],
serviceId: [{value: SystemSettingsComponent.generateId(), disabled: true}, Validators.required]
});
this.form.statusChanges.subscribe(status => {
if (status === 'VALID' && this.form.controls.serviceDesc.disabled) {
this.form.controls.serviceDesc.enable();
} else if (status !== 'VALID' && this.form.controls.serviceDesc.enabled) {
this.form.controls.serviceDesc.disable();
}
});
}
I have been continously trying to implement routing in Angularjs with Mvc 4.0 project but I am not able to do it.
I have created a empty MVC 4.0 project and added a controller "HomeController". Then I added a folder in Views with name Home having three views. One is index which opens when we run application as in route config we have route for homecontroller and Index Action.So, basically assuming the index page as the main page in Singlepage application, I have defined some code in the index page as given in 6oish book enter link description here.
Index. CShtml
#{
ViewBag.Title = "Index";
}
<style>
.container {
float: left;
width: 100%;
}
</style>
<script src="~/Scripts/angular.min.js"></script>
<h2>Practising Angular</h2>
List
Edit
<div ng-app="demoApp">
<div class="container">
<div ng-view=""></div>
</div>
</div>
<script>
var demoApp = angular.module('demoApp', []);
demoApp.config(function ($routeProvider) {
$routeProvider.when('/', { controller: 'SimpleController', templateUrl: 'Home/List' })
.when('/Edit', { controller: 'SimpleController', templateUrl: 'Home/Edit' })
.otherwise({ redirectTo: '/' });
});
demoApp.controller('SimpleController', function ($scope) {
$scope.customers = [{ name: 'Dave jones', city: 'Phoenix' },
{ name: 'Jhon Dena', city: 'Mexico' },
{ name: 'Bradshaw', city: 'WashingTon' },
{ name: 'Rey Mysterio', city: 'Brazil' },
{ name: 'Randy', city: 'California' }, ];
});
$scope.addCustomer = function () {
$scope.customers.push({ name: $scope.newCustomer.name, city: $scope.newCustomer.city })
};
</script>
Now, I need two more Views which are defined in the above route and they are as follows:
List.cshtml
#{
ViewBag.Title = "List";
}
<h2>Listing the users in order </h2>
<div class="container">
Name: <input type="text" ng-model="filter.name" />
<ul>
<li ng-repeat="objCust in customers | filter:filter.name">{{objCust.name }}-{{objCust.city}}
</li>
</ul>
Customer Name:<br />
<input type="text" ng-model="newCustomer.name" /><br />
Customer city:<br />
<input type="text" ng-model="newCustomer.city" /><br />
<button ng-click="addcustomer()">Add customer</button>
</div>
and Last one is
Edit.cshtml
#{
ViewBag.Title = "Edit";
}
<h2>Edit the particular user. Things are under construction</h2>
<h2>Listing the users in order </h2>
<div class="container">
Name: <input type="text" ng-model="city" />
<ul>
<li ng-repeat="objCust in customers | filter:city">{{objCust.name }}-{{objCust.city}}
</li>
</ul>
</div>
Here is the home controller
namespace Routing_Angular.Controllers
{
public class HomeController : Controller
{
//
// GET: /Home/
public ActionResult Index()
{
return View();
}
public ActionResult List()
{
return PartialView();
}
public ActionResult Edit()
{
return PartialView();
}
}
}
I am attaching a image to show the Project structure.
I ma running the application, I can see the empty page where it is written "Practising Angular" with two anchor tags "List" and "Edit". I am not getting any change on changing the url.I added "/" in the url and It is not changed . then I added a "/Edit". then also I found no change. I have added anchor tags at the top in index page then also there is no change. only url gets changed. Please guide me where I am doing wrong.
There are a few things you need to fix in your views and angular code.
First of all, when defining the SimpleController, you have defined the addCustomer function outside the controller.
You should have the following controller definition:
demoApp.controller('SimpleController', function ($scope) {
$scope.customers = [{ name: 'Dave jones', city: 'Phoenix' },
{ name: 'Jhon Dena', city: 'Mexico' },
{ name: 'Bradshaw', city: 'WashingTon' },
{ name: 'Rey Mysterio', city: 'Brazil' },
{ name: 'Randy', city: 'California' }, ];
$scope.addCustomer = function () {
$scope.customers.push({ name: $scope.newCustomer.name, city: $scope.newCustomer.city });
};
});
Then in your list view, the function declared for the "Add Customer" button is wrong, as it is case sensitive. You should have addCustomer instead of addcustomer (with capital C, as defined in your SimpleController):
<button ng-click="addCustomer()">Add customer</button>
Also, I am not sure which version of angular you are using, but from version 1.2.0, routing needs to be loaded as a separate module (see this error). You can install it following these instructions, adding the script angular-route.min.js and declaring your module as:
var demoApp = angular.module('demoApp', ['ngRoute']);
You will know that you need to load the routing module because you will see an exception in the browser console when the initial Index view loads. (It's always a good idea to check the browser console for JS errors anyway)
That should be everything, hope it helps!
I am having a strange problem. I am using AngularJS in my project. I have some partial views where I am having different implementations of AngularJS functionality. I am loading all my partial views via Ajax call. Ajax call does load partial view in container but its AngularJS functionality does not work. I have noticed that when I give reference to AngularJS via CDN then it works but when I copy and paste CDN JS into my local js file then it does not.
Please suggest what is the issue.
Here is the code:
Partial View:
<div ng-controller="EmployeeController">
<div>
ID: <input type="text" id="txtID" ng-model="employeeID" /><br />
Name: <input id="txtName" type="text" ng-model="employeeName" />
<button id="btnAddEmployee" ng-click="addEmployee()">Add Employee</button>
<button id="btnRemoveEmployee" ng-click="removeEmployee()">Remove Employee</button>
<ul >
<li ng-repeat="employee in employees">
Employee id is: {{employee.id}}<br />
Employee name is: {{employee.name}}
</li>
</ul>
</div>
</div>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.0.7/angular.min.js"></script>
<script>
var employees = [{ name: 'ABC', id: '1' },
{ name: 'XYZ', id: '2' },
{ name: 'KKK', id: '3' }];
function EmployeeController($scope) {
$scope.employees = employees;
$scope.addEmployee = function () {
$scope.employees.push({ name: $scope.employeeName, id: $scope.employeeID });
}
$scope.removeEmployee = function () {
$scope.employees.pop();
}
}
</script>
Controller:
public PartialViewResult LoadViews(int id)
{
if (id == 1)
return PartialView("TestView1Partial");
else
return PartialView("TestView2Partial");
}
Main View:
<ul>
<li>
View 2
</li>
</ul>
<div id="dvContainer">
<script>
function LoadView2() {
$.ajax({
url: "/home/LoadViews?id=2",
type: "GET",
datatype: "html",
async:true,
success: function (result) {
$("#dvContainer").html(result);
}
});
}
</script>
Thanks,
JSHunjan
In your Ajax call change the async:false and it might work.
So in Ember if I have a model called "foos" - it will load a template with the data-template-name="foos", however I am not sure how to wipe "foos" from the screen when I load 1 "foo" as well as I am not sure how to can the instance variable in the controller such as #foos to do a #foos.length. for some other stuff I want to do.
Currently my view doesn't load if I call foos.isLoaded as well as if I call foo #4 It will appendTo the page the view. but not redraw the view.
I just don't know how to figure out what the default stuff looks like I guess.
My controller stuff-
Router
App.Router.map(function(){
this.resource('records', function(){
this.resource('record', {path: ':record_id'});
});
});
App.FoosRoute = Ember.Route.extend({
model: function() {
return App.Foo.find();
}
});
// Controller
App.FoosController = Ember.ArrayController.extend({
itemController: 'record'
});
App.FooController = Ember.ObjectController.extend({
fullName: function() {
return this.get('firstName') + ' ' + this.get('middleName') + ' ' + this.get('surname') + ' ' + this.get('suffix')
}.property('firstName', 'middleName', 'surname', 'suffix')
})
// Model
App.Store = DS.Store.extend({
revision: 11,
adapter: 'DS.RESTAdapter'
});
App.Foo = DS.Model.extend({
firstName: DS.attr('string'),
middleName: DS.attr('string')
.....
})
My views:
<script type="text/x-handlebars" data-template-name="application">
{{ outlet }}
</script>
<script type="text/x-handlebars" data-template-name="foos">
<div class="one_half">
<h2>Search</h2>
form here....
</div>
<div class="one_half">
<div id="smallMap">
map
</div>
</div>
<div id="foos">
<table>
<tr>
<th>Name</th>
<th>Birth</th>
<th>Death</th>
</tr>
{{#each foo in controller}}
{{#if foo.isLoaded}}
<tr>
<td>{{#linkTo "foo" foo}} {{foo.fullName}} {{/linkTo}}</td>
<td>{{#linkTo "foo" foo}} {{foo.birthMonth}} {{#if foo.birthMonth}}/{{/if}}{{foo.birthDay}} {{#if foo.birthDay}}/{{/if}}{{foo.birthYear}} {{/linkTo}}</td>
<td>{{#linkTo "foo" foo}}{{foo.deathMonth}}{{#if foo.deathMonth}}/{{/if}}{{foo.deathDay}}{{#if foo.deathDay}}/{{/if}}{{foo.deathYear}}{{/linkTo}} {{foo.trAlt}}</td>
</tr>
{{else}}
<tr>
<td colspan="3" class="loading">Records are loading</td>
</tr>
{{/if}}
{{/each}}
</table>
</div>
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="foo">
<h3>A Record</h3>
{{id}}
{{firstName}}
</script>
Currently it doesn't kill the view and bring in the new ones.
Hmmm - there is a lot going on here, going to try and point you in the right direction.
So in Ember if I have a model called "foos" - it will load a template with the data-template-name="foos"
Not exactly. Convention is to use the same name, but the ember does not load a template based on the model. If anything it's the other way around. Your best bet is usually to start with templates then work your way backwards to the model layer. So in this case let's start with 3 templates - application, foo and foos:
<script type="text/x-handlebars" data-template-name="application">
<h1>Foo App</h1>
{{outlet}}
</script>
<script type="text/x-handlebars" data-template-name="foos">
<h3>All Foos:</h3>
<ul>
{{#each controller}}<li>{{fullName}}</li>{{/each}}
</ul>
</script>
<script type="text/x-handlebars" data-template-name="foo">
<h3>Foo Details:</h3>
<p>{{fullName}}</p>
</script>
however I am not sure how to wipe "foos" from the screen when I load 1 "foo"
Ember will take care of rendering the appropriate view when the route changes. One way to make this possible is by adding links to your application. For example, modify foos template so that each record is a link, and add a Show All link to the detail page.
<script type="text/x-handlebars" data-template-name="foos">
<h3>All Foos:</h3>
<ul>
{{#each controller}}
<li>{{#linkTo "foo" this}}{{fullName}}{{/linkTo}}</li>
{{/each}}
</ul>
</script>
<script type="text/x-handlebars" data-template-name="foo">
<h3>Foo Details:</h3>
<p>{{fullName}}</p>
<p>{{#linkTo foos}}Show all{{/linkTo}}</p>
</script>
as well as I am not sure how to can the instance variable in the controller such as #foos to do a #foos.length for some other stuff I want to do
Not sure what your getting at. #foos is not an instance variable, unless you are using coffeescript and really mean this.foos.
Currently my view doesn't load if I call foos.isLoaded as well as if I call foo #4 It will appendTo the page the view. but not redraw the view.
Right. Calling foos.isLoaded just tells you if the model is loaded, it has nothing to do with the view. What do you mean call foo #4? Seems there might be code you are referencing that didn't get included in your SO post.
I just don't know how to figure out what the default stuff looks like I guess.
OK. I've made some guesses about what you're trying to do and created a working example. Code below, or see this working example on jsbin
First, I've added an application definition. Then changed your routes to be foos instead of records. Also no need for a nested route in this case.
App = Em.Application.create({});
App.Router.map(function(){
this.route('foos', {path: '/'});
this.resource('foo',{path: '/foos/:foo_id'});
});
FooRoute, FoosController and FooController were ok as-is.
App.FoosRoute = Ember.Route.extend({
model: function() {
return App.Foo.find();
}
});
// Controller
App.FoosController = Ember.ArrayController.extend({
itemController: 'foo'
});
App.FooController = Ember.ObjectController.extend({
fullName: function() {
return this.get('firstName') + ' ' + this.get('middleName') + ' ' + this.get('surname') + ' ' + this.get('suffix');
}.property('firstName', 'middleName', 'surname', 'suffix')
});
Added missing properties to App.Foo
App.Foo = DS.Model.extend({
firstName: DS.attr('string'),
middleName: DS.attr('string'),
surname: DS.attr('string'),
suffix: DS.attr('string')
});
Switching to DS.FixtureAdapter and added 4 fixture records to simulate what might be returned by your API
App.Store = DS.Store.extend({
revision: 11,
adapter: DS.FixtureAdapter
});
App.Foo.FIXTURES = [
{id: 1, firstName: 'Michael', middleName: 'Paul'},
{id: 2, firstName: 'Jennifer', middleName: 'Lyn'},
{id: 3, firstName: 'Sophia', middleName: 'Marie'},
{id: 4, firstName: 'Greta', middleName: 'Fae'}
];
Looking to start using Knockout with ASP.NET MVC4. Have watch some examples and encountered the following questions.
Today I write my view models backend, I can totally replace it
with knockout view models on the client side?
Is there anything like DataAnnotations in Knockout for
validation?
Yes, you remove the server view and view models. All are now are now on the client.
See Knockout validation
Also, you may want to check out OData/WCF data services (http://blogs.msdn.com/b/astoriateam/). It basically gives you a Model and Controller. With this approach you server ends up only serving static HTML pages and Model data as AJAX calls. And it also supports "paging" of data.
IMHO, this the way of the future.
Other links of interest:
Authorisation - http://msdn.microsoft.com/en-us/library/dd728284.aspx
Routing - http://blogs.msdn.com/b/rjacobs/archive/2010/04/05/using-system-web-routing-with-data-services-odata.aspx or http://code.msdn.microsoft.com/WCF-Data-Service-with-285746ac
Knockout.js is a great library. But if you ask people what to use knockout or angular.
Most of them will tell you Angular.js is better, though they are very similar.
I use knockout in my projects. And there are many things that can simplify your development.
For example. I use server side validation only. When user clicks on "submit", my javascript collects model and sends it to controller (asyncronously AJAX). Controller has validation, and if validation fails the response would be HTTP:500 and body will be validation result structure, that displays all errors in correct places in HTML.
From user's perspective it seems like client-side validation.
You can see how it works in this example: Create Order Example (Upida.Net).
You can use this library or this
or use this samole
<script id="customMessageTemplate" type="text/html">
<em class="customMessage" data-bind='validationMessage: field'></em>
</script>
<fieldset>
<legend>User: <span data-bind='text: errors().length'></span> errors</legend>
<label>First name: <input data-bind='value: firstName'/></label>
<label>Last name: <input data-bind='value: lastName'/></label>
<div data-bind='validationOptions: { messageTemplate: "customMessageTemplate" }'>
<label>Email: <input data-bind='value: emailAddress' required pattern="#"/></label>
<label>Location: <input data-bind='value: location'/></label>
<label>Age: <input data-bind='value: age' required/></label>
</div>
<label>
Subscriptions:
<select data-bind='value: subscription, options: subscriptionOptions, optionsCaption: "Choose one..."'></select>
</label>
<label>Password: <input data-bind='value: password' type="password"/></label>
<label>Retype password: <input data-bind='value: confirmPassword' type="password"/></label>
<label>10 + 1 = <input data-bind='value: captcha'/></label>
</fieldset>
<button type="button" data-bind='click: submit'>Submit</button>
<br />
<br />
<button type="button" data-bind='click: requireLocation'>Make 'Location' required</button>
ko.validation.rules.pattern.message = 'Invalid.';
ko.validation.configure({
registerExtenders: true,
messagesOnModified: true,
insertMessages: true,
parseInputAttributes: true,
messageTemplate: null
});
var captcha = function (val) {
return val == 11;
};
var mustEqual = function (val, other) {
return val == other();
};
var viewModel = {
firstName: ko.observable().extend({ minLength: 2, maxLength: 10 }),
lastName: ko.observable().extend({ required: true }),
emailAddress: ko.observable().extend({ // custom message
required: { message: 'Please supply your email address.' }
}),
age: ko.observable().extend({ min: 1, max: 100 }),
location: ko.observable(),
subscriptionOptions: ['Technology', 'Music'],
subscription: ko.observable().extend({ required: true }),
password: ko.observable(),
captcha: ko.observable().extend({ // custom validator
validation: { validator: captcha, message: 'Please check.' }
}),
submit: function () {
if (viewModel.errors().length == 0) {
alert('Thank you.');
} else {
alert('Please check your submission.');
viewModel.errors.showAllMessages();
}
}
};
viewModel.confirmPassword = ko.observable().extend({
validation: { validator: mustEqual, message: 'Passwords do not match.', params: viewModel.password }
}),
viewModel.errors = ko.validation.group(viewModel);
viewModel.requireLocation = function () {
viewModel.location.extend({ required: true });
};
ko.applyBindings(viewModel);