require 'volt/page/bindings/base_binding' module Volt class IfBinding < BaseBinding def initialize(volt_app, target, context, binding_name, branches) super(volt_app, target, context, binding_name) getter, template_name = branches[0] @branches = [] @listeners = [] branches.each do |branch| getter, template_name = branch if getter.present? value = getter else # A nil value means this is an unconditional else branch, it # should always be true value = true end @branches << [value, template_name] end # The promise dependency can be invalidated when we need to rerun the update # manually because a promise resolved. @promise_dependency = Dependency.new @computation = lambda do @promise_dependency.depend update end.watch! end def update # Find the true branch true_template = nil @branches.each do |branch| value, template_name = branch if value.is_a?(Proc) begin current_value = @context.instance_eval(&value) if current_value.is_a?(Promise) # If we got a promise, use its value if resolved. if current_value.resolved? # Should call then immediately current_value.then do |value| current_value = value end else # if its not, resolve it and try again. # TODO: we maybe could cache this so we don't have to run a full update again current_value.then do |val| # Run update again @promise_dependency.changed! end current_value = nil end end rescue => e Volt.logger.error("IfBinding:#{object_id} error: #{e.inspect}\n" + `value.toString()`) current_value = false end else current_value = value end if current_value && !current_value.is_a?(Exception) # This branch is currently true true_template = template_name break end end # Change out the template only if the true branch has changed. if @last_true_template != true_template @last_true_template = true_template if @template @template.remove @template = nil end if true_template @template = TemplateRenderer.new(@volt_app, @target, @context, binding_name, true_template) end end end def remove @computation.stop if @computation @computation = nil @template.remove if @template super end end end