The following code allows user's to check a box to include an amenity on a post using MongodB/Node/Express. It is working perfectly to let users select their amenities and then shows those selections as icons.
However I am unable to EDIT these posts in my edit route . That is the problem. See code at bottom. How would I change my code to be able to edit the icons?
// Simplified Schema
var rentalsSchema = new mongoose.Schema({
amenities: Array
});
// User Checks their amenities
<input type="checkbox" name="amenities" value="wifi"><span>Wi-fi</span>
<input type="checkbox" name="amenities" value="tv"><span>TV</span>
// This code loops through the array and shows the relevant icons using Google's material icons.
<div class="list-group">
<li class="list-group-item active">Amenities</li>
<li id="amenitiesBox" class="list-group-item">
<% for(var i=0; i<rentals.amenities.length; i++){ %>
<i class="material-icons"><%=rentals.amenities[i]%></i>
<% } %>
</li>
</li>
</div>
</div>
// The problem is here in my edit route. Simplified below
<form id='rentalEdit' action="/rentals/<%=rentals._id %>/?_method=PUT" method ="POST">
<input Checked type="checkbox" name="rentals[amenities]" value="wifi"><span>Wifi</span>
</form>
Ah got it!
In my router.put I added:
var amenities = req.body.amenities; & amenities: amenities.
Then I just added my amenities to the edit form in this format.
<input name="amenities" type="checkbox" value="wifi" <%= rentals.amenities.indexOf("wifi") !== -1 ? "checked" : "" %> >wifi
Related
I'm new at learning AngularJS and what I'm trying is to display an image if a checkbox is checked.
<body ng-app="imgApp" ng-controller="imgCNTRL">
<li class="stay-item" name="hotel" id="hotel1">
<h2>Hotel Grande Bretagne</h2>
<img src="https://www.fivestaralliance.com/files/fivestaralliance.com/field/image/nodes/2009/10181/10181_0_hotelgrandebretagne_fsa-g.jpg">
<p class="img__description">
Facilities
<br><br>
2 swimming pools
<br>
Free WiFi
<br>
Parking
<br>
Spa / Sallon
<br>
Bar
<br>
</p>
<br><br>
<div class="form-check">
<input class="form-check-input" type="checkbox" id="reserv" name="reserv">
<label class="form-check-label" for="reserv">Reservation</label>
</div>
</li>
My code so far is this:
<script>
var app = angular.module('imgApp', []);
app.controller('imgCNTRL', function($scope){
$(document).ready(function(){
$('input[name=reserv1]').click(function(){
alert('ok');
$scope.img1 = "https://t-cf.bstatic.com/xdata/images/hotel/max1024x768/328010584.jpg?k=f8243c30e30a6671e3a618ed132f42d10bccd185b464caec8e7bbcb82915d837&o=&hp=1";
});
});
});
</script>
What I want to achieve is, If I click the button with the id="reserv", this image would be displayed(image). Is there any convenient way to achieve that?
Just add an ng-model="reserv_chk" to your checkbox and an ng-show="reserv_chk" to your img:
https://codesandbox.io/s/zealous-edison-uue0ti?file=/index.html
This is my HTML code in angular template. In my controller I have
$scope.contacts.
Every contact in $scope.contacts can have multiple contact.fields. You can see I have 2 ng-repeat here, for every contact and every contact.field. User can add contact manually, and for every contact it is defined how many fields it has. So user click on plus and contact with empty fields is added. My question is: how to bind view with $scope.contacts, so when user adds new contact, it shows up in $scope.contacts?
<div id="contactsContainer">
<div id="{{contact.divId}}" ng-style="{'border': contact.borderStyle}"
class="form-group {{contact.divId}}" ng-mouseover="hoverIn()"
ng-mouseleave="hoverOut()" ng-repeat="contact in contacts track by $index">
<label class="col-sm-3 control-label">{{ translate[contact.keyTranslationName]}}</label>
<div id="fieldContainer" class="col-sm-4">
<div id="currentField" class="row mb5"
ng-repeat="field in contact.field track by $index">
<div id="{{contact.idPersonContact}}"
class="{{field.width}} has-icon pull-left">
<input name="{{field.name}}"
id="{{field.id}}"
placeholder="{{ translate[field.keyTranslationPlaceholder] }}"
class="form-control" value="{{field.value}}"
style="background-image: url();background-position: left;background-repeat: no-repeat;background-size:20px;">
</div>
</div>
</div>
</div>
<input type="button" ng-click="addContact()" />
// Controller
$scope.addContact = function(){
$scope.contacts.push({field : []});
// or field : Array(defaultFieldSize)
$scope.contacts.push({field : new Array(5) }); // Contact with 5 empty fields
}
Adding a contact in the contacts collection would do it. So when the user creates the new contact using the button you would do something like:
var newContact = {
field1:'',
field2: ''
...
}
and then just add the new contact to the contacts collection.
$scope.contacts.push(newContact);
ng-repeat will detect the change in the collection and render it.
I have a group object that contains a list of video
And when you edit the object, i give the HTML a list of all videos, where you can search in.
But if you don't search I want it to show only the videos that are checked.
here is the HTML used
<div class="input-field">
<input type="text" id="filter" ng-model="query" ng-change="hasVideos()" />
<label for="filter"><i class="mdi-action-search"></i></label>
</div>
<ul class="collection">
<li class="collection-item" ng-repeat="video in filterdVideo = (videos | filter:query) ">
<p>
<input type="checkbox" id="video_{{video.Id}}" checklist-model="group.Keywords" checklist-value="video.Id">
<label for="video_{{video.Id}}">
{{video.Title}}
</label>
</p>
</li>
</ul>
So how can I make it that it only shows the video list where the checkbox is checked? and when the query isn't empty to ignore that and show all.
I will try to improve my answer later.
But for a quick guess you might be able to use ng-if and let the controller handle if something should be listet.
<li ng-if="functionthatreturnstrueorfalsebasedonyourneeds" class="collection-item" ng-repeat="video in filterdVideo = (videos | filter:query) ">
Checkbox example can be found in the docs:
https://docs.angularjs.org/api/ng/directive/ngIf
Fixed it by doing a filter:
filter('filterStack', function () {
return function (inputs, filterValues, showAll) {
var output = [];
if (showAll) return inputs;
angular.forEach(inputs, function (input) {
angular.forEach(filterValues, function (filterVal) {
if (filterVal.Id == input.Id) {
output.push(input);
}
});
});
return output;
};
})
but having an other issue now, when loading it in with data: https://stackoverflow.com/questions/29749006/angular-checklist-model-not-checking
I am loading a todos list, every todo has a flag field which if true the ng-class should apply. When loading data into the page ng-class is applied if I use ng-class="{'completed': todo.isCompleted=='true'}", but then it doesn't work when I play with the checkboxes.
On the other hand if I use ng-class="{'completed': todo.isCompleted==true}" instead (without the quotes on the true), it loads the data without applying the ng-class at the beginning, means loading all as if they are false, but then it works fine when playing with the checkboxes.
It has been driving me crazy, couldn't figure out why.
<ul id="todo-list">
<li ng-repeat="todo in todos" ng-class="{'completed': todo.isCompleted==true}" class="editing">
<div class="view" >
<input class="toggle" type="checkbox" ng-click="complete(todo)" ng-model="todo.isCompleted" ng-checked="{{todo.isCompleted}}">
<label ng-hide="isEditing" ng-dblclick="isEditing = !isEditing">{{todo.title}}</label>
<button class="destroy" ng-click="remove(todo)"></button>
</div>
<input class="edit" ng-show="isEditing" ng-model="todo.title" ng-blur="isEditing = !isEditing;edit(todo);">
</li>
</ul>
Controller
$scope.complete = function(todo) {
$scope.insertTodo(todo, UPDATE);
};
Any help is appreciated.
Have you tried to change
ng-class="{'completed': todo.isCompleted==true}"
to
ng-class="{'completed': todo.isCompleted}"
Or, one of those
ng-class="todo.isCompleted ? 'completed' : ''"
ng-class="{true: 'completed', false: ''}[todo.isCompleted]"
So, it looks like your server is returning the boolean values as strings, that's why your bindings don't work...
You can either change your server's return values (preferred) or add ng-true-value and ng-false-value to your check box and keep the binding on ng-class using the string comparison:
<ul id="todo-list">
<li ng-repeat="todo in todos" ng-class="{'completed': todo.isCompleted=='true'}" class="editing">
<div class="view" >
<input class="toggle" type="checkbox" ng-click="complete(todo)" ng-model="todo.isCompleted" ng-checked="{{todo.isCompleted}}" ng-true-value="'true'" ng-false-value="'false'">
<label ng-hide="isEditing" ng-dblclick="isEditing = !isEditing">{{todo.title}}</label>
<button class="destroy" ng-click="remove(todo)"></button>
</div>
<input class="edit" ng-show="isEditing" ng-model="todo.title" ng-blur="isEditing = !isEditing;edit(todo);">
</li>
</ul>
Hope that helps
The problem I'm facing, as outlined in the code, is that I can't seem to find out how to bind the second checkboxes (created with ng-repeat) to some model which I would then be able to use further down the code (showing/hiding yet another set of options). Also, I managed to show the additional number of inputs based on the count parameter in the $scope.availableOptions by using the $scope.getItterator function, but now I don't see how would I access the values of these checkboxes? I know I have to somehow use the option "ng-model" but am failing to do so, so any help appreciated.
My code is here, but am showing it here too:
html:
<div ng-controller='MyCtrl'>
Show additional options <input type="checkbox" ng-model="additionalOptions">
<div ng-show="additionalOptions">
<ul>
<li ng-repeat="option in availableOptions">
<label class="checkbox" for="opt_{{option.id}}">
<input type="checkbox" name="opt_{{option.id}}" id="opt_{{option.}}" />
{{option.name}}
<ul ng-show="if the upper checkbox is clicked">
<li>
<input type="text" ng-repeat="i in getItterator(option.count)" ng-model="SOME_VALUE_TO_BE_USED_BELOW"/>
Output the value based on what's entered above in the textboxes (SOME_VALUE_TO_BE_USED_BELOW)
</li>
</ul>
</label>
</li>
</ul>
</div>
</div>
and my js:
function MyCtrl($scope) {
$scope.availableOptions = [{"id":"1","name":"easy","count":"2"},{"id":"2","name":"medium","count":"3"},{"id":"3","name":"hard","count":"2"}];
$scope.getItterator=function(n){
var a = new Array();
for(var i=1; i <= n; i++)
a.push(i);
return a;
};
}
Try ng-model="option.checked":
<input type="checkbox" name="opt_{{option.id}}" id="opt_{{option.}}" ng-model="option.checked"/>
And then you can access this property further below like this:
<ul ng-show="option.checked">
DEMO
If you need to also reference the text box inputs. You create a new property (values) on the option. Like this:
{"id":"1","name":"easy","count":"2",values:[]}
Html:
<div ng-repeat="i in getItterator(option.count)">
<input type="text" ng-model="option.values[$index]"/>
{{option.values[$index]}}
</div>
DEMO
Use this:
<input type="checkbox" name="opt_{{option.id}}" id="opt_{{option.}}" ng-model="option.clicked"/>
{{option.name}}
<ul ng-show="option.clicked">
Basically, you are saying that the top checkbox should store its value in a model for each option option.clicked. And then only showing the information based on the scope item.
Updated Fiddle:
http://jsfiddle.net/CkHhJ/26/
UPDATE:
Here is another updated fiddle to answer your questions second part: http://jsfiddle.net/CkHhJ/27/
The difficulties you were having is likely because you are trying to build dynamic input models. Just bear in mind that you need to use an object for the dynamic values (not a plain string, eg: option.answers[$index].value and not just option.answers[$index]. See: AngularJS: Updating an input with a dynamic ng-model blurs on each key press